Merge "External camera: add device config file"
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
new file mode 100644
index 0000000..6e217d9
--- /dev/null
+++ b/audio/4.0/Android.bp
@@ -0,0 +1,48 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.audio@4.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IDevicesFactory.hal",
+        "IPrimaryDevice.hal",
+        "IStream.hal",
+        "IStreamIn.hal",
+        "IStreamOut.hal",
+        "IStreamOutCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio.common@4.0",
+        "android.hardware.audio.effect@4.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "AudioDrain",
+        "AudioFrequencyResponsePoint",
+        "AudioMicrophoneChannelMapping",
+        "AudioMicrophoneCoordinate",
+        "AudioMicrophoneDirectionality",
+        "AudioMicrophoneLocation",
+        "DeviceAddress",
+        "MessageQueueFlagBits",
+        "MicrophoneInfo",
+        "MmapBufferFlag",
+        "MmapBufferInfo",
+        "MmapPosition",
+        "ParameterValue",
+        "PlaybackTrackMetadata",
+        "RecordTrackMetadata",
+        "Result",
+        "SinkMetadata",
+        "SourceMetadata",
+        "TimeSpec",
+    ],
+    gen_java: false,
+    gen_java_constants: true,
+}
+
diff --git a/audio/4.0/IDevice.hal b/audio/4.0/IDevice.hal
new file mode 100644
index 0000000..bb58568
--- /dev/null
+++ b/audio/4.0/IDevice.hal
@@ -0,0 +1,271 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStreamIn;
+import IStreamOut;
+
+interface IDevice {
+    /**
+     * Returns whether the audio hardware interface has been initialized.
+     *
+     * @return retval OK on success, NOT_INITIALIZED on failure.
+     */
+    initCheck() generates (Result retval);
+
+    /**
+     * Sets the audio volume for all audio activities other than voice call. If
+     * NOT_SUPPORTED is returned, the software mixer will emulate this
+     * capability.
+     *
+     * @param volume 1.0f means unity, 0.0f is zero.
+     * @return retval operation completion status.
+     */
+    setMasterVolume(float volume) generates (Result retval);
+
+    /**
+     * Get the current master volume value for the HAL, if the HAL supports
+     * master volume control. For example, AudioFlinger will query this value
+     * from the primary audio HAL when the service starts and use the value for
+     * setting the initial master volume across all HALs. HALs which do not
+     * support this method must return NOT_SUPPORTED in 'retval'.
+     *
+     * @return retval operation completion status.
+     * @return volume 1.0f means unity, 0.0f is zero.
+     */
+    getMasterVolume() generates (Result retval, float volume);
+
+    /**
+     * Sets microphone muting state.
+     *
+     * @param mute whether microphone is muted.
+     * @return retval operation completion status.
+     */
+    setMicMute(bool mute) generates (Result retval);
+
+    /**
+     * Gets whether microphone is muted.
+     *
+     * @return retval operation completion status.
+     * @return mute whether microphone is muted.
+     */
+    getMicMute() generates (Result retval, bool mute);
+
+    /**
+     * Set the audio mute status for all audio activities. If the return value
+     * is NOT_SUPPORTED, the software mixer will emulate this capability.
+     *
+     * @param mute whether audio is muted.
+     * @return retval operation completion status.
+     */
+    setMasterMute(bool mute) generates (Result retval);
+
+    /**
+     * Get the current master mute status for the HAL, if the HAL supports
+     * master mute control. AudioFlinger will query this value from the primary
+     * audio HAL when the service starts and use the value for setting the
+     * initial master mute across all HALs. HAL must indicate that the feature
+     * is not supported by returning NOT_SUPPORTED status.
+     *
+     * @return retval operation completion status.
+     * @return mute whether audio is muted.
+     */
+    getMasterMute() generates (Result retval, bool mute);
+
+    /**
+     * Returns audio input buffer size according to parameters passed or
+     * INVALID_ARGUMENTS if one of the parameters is not supported.
+     *
+     * @param config audio configuration.
+     * @return retval operation completion status.
+     * @return bufferSize input buffer size in bytes.
+     */
+    getInputBufferSize(AudioConfig config)
+            generates (Result retval, uint64_t bufferSize);
+
+    /**
+     * This method creates and opens the audio hardware output stream.
+     * If the stream can not be opened with the proposed audio config,
+     * HAL must provide suggested values for the audio config.
+     *
+     * @param ioHandle handle assigned by AudioFlinger.
+     * @param device device type and (if needed) address.
+     * @param config stream configuration.
+     * @param flags additional flags.
+     * @param sourceMetadata Description of the audio that will be played.
+                             May be used by implementations to configure hardware effects.
+     * @return retval operation completion status.
+     * @return outStream created output stream.
+     * @return suggestedConfig in case of invalid parameters, suggested config.
+     */
+    openOutputStream(
+            AudioIoHandle ioHandle,
+            DeviceAddress device,
+            AudioConfig config,
+            bitfield<AudioOutputFlag> flags,
+            SourceMetadata sourceMetadata) generates (
+                    Result retval,
+                    IStreamOut outStream,
+                    AudioConfig suggestedConfig);
+
+    /**
+     * This method creates and opens the audio hardware input stream.
+     * If the stream can not be opened with the proposed audio config,
+     * HAL must provide suggested values for the audio config.
+     *
+     * @param ioHandle handle assigned by AudioFlinger.
+     * @param device device type and (if needed) address.
+     * @param config stream configuration.
+     * @param flags additional flags.
+     * @param source source specification.
+     * @param sinkMetadata Description of the audio that is suggested by the client.
+     *                     May be used by implementations to configure hardware effects.
+     * @return retval operation completion status.
+     * @return inStream in case of success, created input stream.
+     * @return suggestedConfig in case of invalid parameters, suggested config.
+     */
+    openInputStream(
+            AudioIoHandle ioHandle,
+            DeviceAddress device,
+            AudioConfig config,
+            bitfield<AudioInputFlag> flags,
+            SinkMetadata sinkMetadata) generates (
+                    Result retval,
+                    IStreamIn inStream,
+                    AudioConfig suggestedConfig);
+
+    /**
+     * Returns whether HAL supports audio patches.
+     *
+     * @return supports true if audio patches are supported.
+     */
+    supportsAudioPatches() generates (bool supports);
+
+    /**
+     * Creates an audio patch between several source and sink ports.  The handle
+     * is allocated by the HAL and must be unique for this audio HAL module.
+     *
+     * @param sources patch sources.
+     * @param sinks patch sinks.
+     * @return retval operation completion status.
+     * @return patch created patch handle.
+     */
+    createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
+            generates (Result retval, AudioPatchHandle patch);
+
+    /**
+     * Release an audio patch.
+     *
+     * @param patch patch handle.
+     * @return retval operation completion status.
+     */
+    releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
+
+    /**
+     * Returns the list of supported attributes for a given audio port.
+     *
+     * As input, 'port' contains the information (type, role, address etc...)
+     * needed by the HAL to identify the port.
+     *
+     * As output, 'resultPort' contains possible attributes (sampling rates,
+     * formats, channel masks, gain controllers...) for this port.
+     *
+     * @param port port identifier.
+     * @return retval operation completion status.
+     * @return resultPort port descriptor with all parameters filled up.
+     */
+    getAudioPort(AudioPort port)
+            generates (Result retval, AudioPort resultPort);
+
+    /**
+     * Set audio port configuration.
+     *
+     * @param config audio port configuration.
+     * @return retval operation completion status.
+     */
+    setAudioPortConfig(AudioPortConfig config) generates (Result retval);
+
+    /**
+     * Gets the HW synchronization source of the device. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_HW_AV_SYNC on the legacy HAL.
+     * Optional method
+     *
+     * @return retval operation completion status: OK or NOT_SUPPORTED.
+     * @return hwAvSync HW synchronization source
+     */
+    getHwAvSync() generates (Result retval, AudioHwSync hwAvSync);
+
+    /**
+     * Sets whether the screen is on. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_KEY_SCREEN_STATE on the legacy HAL.
+     * Optional method
+     *
+     * @param turnedOn whether the screen is turned on.
+     * @return retval operation completion status.
+     */
+    setScreenState(bool turnedOn) generates (Result retval);
+
+    /**
+     * Generic method for retrieving vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Multiple parameters can be retrieved at the same time.
+     * The implementation should return as many requested parameters
+     * as possible, even if one or more is not supported
+     *
+     * @param context provides more information about the request
+     * @param keys keys of the requested parameters
+     * @return retval operation completion status.
+     *         OK must be returned if keys is empty.
+     *         NOT_SUPPORTED must be returned if at least one key is unknown.
+     * @return parameters parameter key value pairs.
+     *         Must contain the value of all requested keys if retval == OK
+     */
+    getParameters(vec<ParameterValue> context, vec<string> keys)
+            generates (Result retval, vec<ParameterValue> parameters);
+
+    /**
+     * Generic method for setting vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Multiple parameters can be set at the same time though this is
+     * discouraged as it make failure analysis harder.
+     *
+     * If possible, a failed setParameters should not impact the platform state.
+     *
+     * @param context provides more information about the request
+     * @param parameters parameter key value pairs.
+     * @return retval operation completion status.
+     *         All parameters must be successfully set for OK to be returned
+     */
+    setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+            generates (Result retval);
+
+    /**
+     * Returns an array with available microphones in device.
+     *
+     * @return retval INVALID_STATE if the call is not successful,
+     *                OK otherwise.
+     *
+     * @return microphones array with microphones info
+     */
+    getMicrophones()
+         generates(Result retval, vec<MicrophoneInfo> microphones);
+};
diff --git a/audio/4.0/IDevicesFactory.hal b/audio/4.0/IDevicesFactory.hal
new file mode 100644
index 0000000..c552c6d
--- /dev/null
+++ b/audio/4.0/IDevicesFactory.hal
@@ -0,0 +1,59 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IDevice;
+
+interface IDevicesFactory {
+    /** Allows a HAL implementation to be split in multiple independent
+     *  devices (called module in the pre-treble API).
+     *  Note that this division is arbitrary and implementation are free
+     *  to only have a Primary.
+     *  The framework will query the devices according to audio_policy_configuration.xml
+     *
+     *  Each Device value is interchangeable with any other and the framework
+     *  does not differentiate between values with the following exceptions:
+     *  - the Primary device must always be present
+     *  - the R_SUBMIX that is used to forward audio of REMOTE_SUBMIX DEVICES
+     */
+    enum Device : int32_t {
+        PRIMARY,
+        A2DP,
+        USB,
+        R_SUBMIX,
+        STUB,
+        CODEC_OFFLOAD,
+        SECONDARY,
+        AUXILIARY,
+        /** Multi Stream Decoder */
+        MSD
+    };
+
+    /**
+     * Opens an audio device. To close the device, it is necessary to release
+     * references to the returned device object.
+     *
+     * @param device device type.
+     * @return retval operation completion status. Returns INVALID_ARGUMENTS
+     *         if there is no corresponding hardware module found,
+     *         NOT_INITIALIZED if an error occured while opening the hardware
+     *         module.
+     * @return result the interface for the created device.
+     */
+    openDevice(Device device) generates (Result retval, IDevice result);
+};
diff --git a/audio/4.0/IPrimaryDevice.hal b/audio/4.0/IPrimaryDevice.hal
new file mode 100644
index 0000000..f3d904c
--- /dev/null
+++ b/audio/4.0/IPrimaryDevice.hal
@@ -0,0 +1,124 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IDevice;
+
+interface IPrimaryDevice extends IDevice {
+    /**
+     * Sets the audio volume of a voice call.
+     *
+     * @param volume 1.0f means unity, 0.0f is zero.
+     * @return retval operation completion status.
+     */
+    setVoiceVolume(float volume) generates (Result retval);
+
+    /**
+     * This method is used to notify the HAL about audio mode changes.
+     *
+     * @param mode new mode.
+     * @return retval operation completion status.
+     */
+    setMode(AudioMode mode) generates (Result retval);
+
+    /**
+     * Gets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+     * Calling this method is equivalent to getting AUDIO_PARAMETER_KEY_BT_NREC
+     * on the legacy HAL.
+     *
+     * @return retval operation completion status.
+     * @return enabled whether BT SCO NR + EC are enabled.
+     */
+    getBtScoNrecEnabled() generates (Result retval, bool enabled);
+
+    /**
+     * Sets whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+     * Calling this method is equivalent to setting AUDIO_PARAMETER_KEY_BT_NREC
+     * on the legacy HAL.
+     * Optional method
+     *
+     * @param enabled whether BT SCO NR + EC are enabled.
+     * @return retval operation completion status.
+     */
+    setBtScoNrecEnabled(bool enabled) generates (Result retval);
+
+    /**
+     * Gets whether BT SCO Wideband mode is enabled. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+     *
+     * @return retval operation completion status.
+     * @return enabled whether BT Wideband is enabled.
+     */
+    getBtScoWidebandEnabled() generates (Result retval, bool enabled);
+
+    /**
+     * Sets whether BT SCO Wideband mode is enabled. Calling this method is
+     * equivalent to setting AUDIO_PARAMETER_KEY_BT_SCO_WB on the legacy HAL.
+     * Optional method
+     *
+     * @param enabled whether BT Wideband is enabled.
+     * @return retval operation completion status.
+     */
+    setBtScoWidebandEnabled(bool enabled) generates (Result retval);
+
+    enum TtyMode : int32_t {
+        OFF,
+        VCO,
+        HCO,
+        FULL
+    };
+
+    /**
+     * Gets current TTY mode selection. Calling this method is equivalent to
+     * getting AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+     *
+     * @return retval operation completion status.
+     * @return mode TTY mode.
+     */
+    getTtyMode() generates (Result retval, TtyMode mode);
+
+    /**
+     * Sets current TTY mode. Calling this method is equivalent to setting
+     * AUDIO_PARAMETER_KEY_TTY_MODE on the legacy HAL.
+     *
+     * @param mode TTY mode.
+     * @return retval operation completion status.
+     */
+    setTtyMode(TtyMode mode) generates (Result retval);
+
+    /**
+     * Gets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+     * enabled. Calling this method is equivalent to getting
+     * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+     *
+     * @return retval operation completion status.
+     * @return enabled whether HAC mode is enabled.
+     */
+    getHacEnabled() generates (Result retval, bool enabled);
+
+    /**
+     * Sets whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is
+     * enabled. Calling this method is equivalent to setting
+     * AUDIO_PARAMETER_KEY_HAC on the legacy HAL.
+     * Optional method
+     *
+     * @param enabled whether HAC mode is enabled.
+     * @return retval operation completion status.
+     */
+    setHacEnabled(bool enabled) generates (Result retval);
+};
diff --git a/audio/4.0/IStream.hal b/audio/4.0/IStream.hal
new file mode 100644
index 0000000..f05d7b0
--- /dev/null
+++ b/audio/4.0/IStream.hal
@@ -0,0 +1,322 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import android.hardware.audio.effect@4.0::IEffect;
+
+interface IStream {
+    /**
+     * Return the frame size (number of bytes per sample).
+     *
+     * @return frameSize frame size in bytes.
+     */
+    getFrameSize() generates (uint64_t frameSize);
+
+    /**
+     * Return the frame count of the buffer. Calling this method is equivalent
+     * to getting AUDIO_PARAMETER_STREAM_FRAME_COUNT on the legacy HAL.
+     *
+     * @return count frame count.
+     */
+    getFrameCount() generates (uint64_t count);
+
+    /**
+     * Return the size of input/output buffer in bytes for this stream.
+     * It must be a multiple of the frame size.
+     *
+     * @return buffer buffer size in bytes.
+     */
+    getBufferSize() generates (uint64_t bufferSize);
+
+    /**
+     * Return the sampling rate in Hz.
+     *
+     * @return sampleRateHz sample rate in Hz.
+     */
+    getSampleRate() generates (uint32_t sampleRateHz);
+
+    /**
+     * Return supported native sampling rates of the stream for a given format.
+     * A supported native sample rate is a sample rate that can be efficiently
+     * played by the hardware (typically without sample-rate conversions).
+     *
+     * This function is only called for dynamic profile. If called for
+     * non-dynamic profile is should return NOT_SUPPORTED or the same list
+     * as in audio_policy_configuration.xml.
+     *
+     * Calling this method is equivalent to getting
+     * AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES on the legacy HAL.
+     *
+     *
+     * @param format audio format for which the sample rates are supported.
+     * @return retval operation completion status.
+     *                Must be OK if the format is supported.
+     * @return sampleRateHz supported sample rates.
+     */
+    getSupportedSampleRates(AudioFormat format)
+            generates (Result retval, vec<uint32_t> sampleRates);
+
+    /**
+     * Sets the sampling rate of the stream. Calling this method is equivalent
+     * to setting AUDIO_PARAMETER_STREAM_SAMPLING_RATE on the legacy HAL.
+     * Optional method. If implemented, only called on a stopped stream.
+     *
+     * @param sampleRateHz sample rate in Hz.
+     * @return retval operation completion status.
+     */
+    setSampleRate(uint32_t sampleRateHz) generates (Result retval);
+
+    /**
+     * Return the channel mask of the stream.
+     *
+     * @return mask channel mask.
+     */
+    getChannelMask() generates (bitfield<AudioChannelMask> mask);
+
+    /**
+     * Return supported channel masks of the stream. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_CHANNELS on the legacy
+     * HAL.
+     *
+     * @param format audio format for which the channel masks are supported.
+     * @return retval operation completion status.
+     *                Must be OK if the format is supported.
+     * @return masks supported audio masks.
+     */
+    getSupportedChannelMasks(AudioFormat format)
+            generates (Result retval, vec<bitfield<AudioChannelMask>> masks);
+
+    /**
+     * Sets the channel mask of the stream. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_STREAM_CHANNELS on the legacy HAL.
+     * Optional method
+     *
+     * @param format audio format.
+     * @return retval operation completion status.
+     */
+    setChannelMask(bitfield<AudioChannelMask> mask) generates (Result retval);
+
+    /**
+     * Return the audio format of the stream.
+     *
+     * @return format audio format.
+     */
+    getFormat() generates (AudioFormat format);
+
+    /**
+     * Return supported audio formats of the stream. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_FORMATS on the legacy
+     * HAL.
+     *
+     * @return formats supported audio formats.
+     */
+    getSupportedFormats() generates (vec<AudioFormat> formats);
+
+    /**
+     * Sets the audio format of the stream. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_STREAM_FORMAT on the legacy HAL.
+     * Optional method
+     *
+     * @param format audio format.
+     * @return retval operation completion status.
+     */
+    setFormat(AudioFormat format) generates (Result retval);
+
+    /**
+     * Convenience method for retrieving several stream parameters in
+     * one transaction.
+     *
+     * @return sampleRateHz sample rate in Hz.
+     * @return mask channel mask.
+     * @return format audio format.
+     */
+    getAudioProperties() generates (
+            uint32_t sampleRateHz, bitfield<AudioChannelMask> mask, AudioFormat format);
+
+    /**
+     * Applies audio effect to the stream.
+     *
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect to apply.
+     * @return retval operation completion status.
+     */
+    addEffect(uint64_t effectId) generates (Result retval);
+
+    /**
+     * Stops application of the effect to the stream.
+     *
+     * @param effectId effect ID (obtained from IEffectsFactory.createEffect) of
+     *                 the effect to remove.
+     * @return retval operation completion status.
+     */
+    removeEffect(uint64_t effectId) generates (Result retval);
+
+    /**
+     * Put the audio hardware input/output into standby mode.
+     * Driver must exit from standby mode at the next I/O operation.
+     *
+     * @return retval operation completion status.
+     */
+    standby() generates (Result retval);
+
+    /**
+     * Return the set of device(s) which this stream is connected to.
+     * Optional method
+     *
+     * @return retval operation completion status: OK or NOT_SUPPORTED.
+     * @return device set of device(s) which this stream is connected to.
+     */
+    getDevice() generates (Result retval, bitfield<AudioDevice> device);
+
+    /**
+     * Connects the stream to the device.
+     *
+     * This method must only be used for HALs that do not support
+     * 'IDevice.createAudioPatch' method. Calling this method is
+     * equivalent to setting AUDIO_PARAMETER_STREAM_ROUTING in the legacy HAL
+     * interface.
+     *
+     * @param address device to connect the stream to.
+     * @return retval operation completion status.
+     */
+    setDevice(DeviceAddress address) generates (Result retval);
+
+    /**
+     * Notifies the stream about device connection state. Calling this method is
+     * equivalent to setting AUDIO_PARAMETER_DEVICE_[DIS]CONNECT on the legacy
+     * HAL.
+     *
+     * @param address audio device specification.
+     * @param connected whether the device is connected.
+     * @return retval operation completion status.
+     */
+    setConnectedState(DeviceAddress address, bool connected)
+            generates (Result retval);
+
+    /**
+     * Sets the HW synchronization source. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_STREAM_HW_AV_SYNC on the legacy HAL.
+     * Optional method
+     *
+     * @param hwAvSync HW synchronization source
+     * @return retval operation completion status.
+     */
+    setHwAvSync(AudioHwSync hwAvSync) generates (Result retval);
+
+    /**
+     * Generic method for retrieving vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Multiple parameters can be retrieved at the same time.
+     * The implementation should return as many requested parameters
+     * as possible, even if one or more is not supported
+     *
+     * @param context provides more information about the request
+     * @param keys keys of the requested parameters
+     * @return retval operation completion status.
+     *         OK must be returned if keys is empty.
+     *         NOT_SUPPORTED must be returned if at least one key is unknown.
+     * @return parameters parameter key value pairs.
+     *         Must contain the value of all requested keys if retval == OK
+     */
+    getParameters(vec<ParameterValue> context, vec<string> keys)
+            generates (Result retval, vec<ParameterValue> parameters);
+
+    /**
+     * Generic method for setting vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Multiple parameters can be set at the same time though this is
+     * discouraged as it make failure analysis harder.
+     *
+     * If possible, a failed setParameters should not impact the platform state.
+     *
+     * @param context provides more information about the request
+     * @param parameters parameter key value pairs.
+     * @return retval operation completion status.
+     *         All parameters must be successfully set for OK to be returned
+     */
+    setParameters(vec<ParameterValue> context, vec<ParameterValue> parameters)
+            generates (Result retval);
+
+    /**
+     * Called by the framework to start a stream operating in mmap mode.
+     * createMmapBuffer() must be called before calling start().
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     */
+    start() generates (Result retval);
+
+    /**
+     * Called by the framework to stop a stream operating in mmap mode.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the succes.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     */
+    stop() generates (Result retval) ;
+
+    /**
+     * Called by the framework to retrieve information on the mmap buffer used for audio
+     * samples transfer.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @param minSizeFrames minimum buffer size requested. The actual buffer
+     *                     size returned in struct MmapBufferInfo can be larger.
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                NOT_INITIALIZED in case of memory allocation error
+     *                INVALID_ARGUMENTS if the requested buffer size is too large
+     *                INVALID_STATE if called out of sequence
+     * @return info    a MmapBufferInfo struct containing information on the MMMAP buffer created.
+     */
+    createMmapBuffer(int32_t minSizeFrames)
+            generates (Result retval, MmapBufferInfo info);
+
+    /**
+     * Called by the framework to read current read/write position in the mmap buffer
+     * with associated time stamp.
+     * Function only implemented by streams operating in mmap mode.
+     *
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED on non mmap mode streams
+     *                INVALID_STATE if called out of sequence
+     * @return position a MmapPosition struct containing current HW read/write position in frames
+     *                  with associated time stamp.
+     */
+    getMmapPosition()
+            generates (Result retval, MmapPosition position);
+
+    /**
+     * Called by the framework to deinitialize the stream and free up
+     * all the currently allocated resources. It is recommended to close
+     * the stream on the client side as soon as it is becomes unused.
+     *
+     * @return retval OK in case the success.
+     *                NOT_SUPPORTED if called on IStream instead of input or
+     *                              output stream interface.
+     *                INVALID_STATE if the stream was already closed.
+     */
+    close() generates (Result retval);
+};
diff --git a/audio/4.0/IStreamIn.hal b/audio/4.0/IStreamIn.hal
new file mode 100644
index 0000000..247e826
--- /dev/null
+++ b/audio/4.0/IStreamIn.hal
@@ -0,0 +1,168 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStream;
+
+interface IStreamIn extends IStream {
+    /**
+     * Returns the source descriptor of the input stream. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_STREAM_INPUT_SOURCE on the legacy
+     * HAL.
+     * Optional method
+     *
+     * @return retval operation completion status.
+     * @return source audio source.
+     */
+    getAudioSource() generates (Result retval, AudioSource source);
+
+    /**
+     * Set the input gain for the audio driver.
+     * Optional method
+     *
+     * @param gain 1.0f is unity, 0.0f is zero.
+     * @result retval operation completion status.
+     */
+    setGain(float gain) generates (Result retval);
+
+    /**
+     * Commands that can be executed on the driver reader thread.
+     */
+    enum ReadCommand : int32_t {
+        READ,
+        GET_CAPTURE_POSITION
+    };
+
+    /**
+     * Data structure passed to the driver for executing commands
+     * on the driver reader thread.
+     */
+    struct ReadParameters {
+        ReadCommand command;  // discriminator
+        union Params {
+            uint64_t read;    // READ command, amount of bytes to read, >= 0.
+            // No parameters for GET_CAPTURE_POSITION.
+        } params;
+    };
+
+    /**
+     * Data structure passed back to the client via status message queue
+     * of 'read' operation.
+     *
+     * Possible values of 'retval' field:
+     *  - OK, read operation was successful;
+     *  - INVALID_ARGUMENTS, stream was not configured properly;
+     *  - INVALID_STATE, stream is in a state that doesn't allow reads.
+     */
+    struct ReadStatus {
+        Result retval;
+        ReadCommand replyTo;  // discriminator
+        union Reply {
+            uint64_t read;    // READ command, amount of bytes read, >= 0.
+            struct CapturePosition { // same as generated by getCapturePosition.
+                uint64_t frames;
+                uint64_t time;
+            } capturePosition;
+        } reply;
+    };
+
+    /**
+     * Called when the metadata of the stream's sink has been changed.
+     * @param sinkMetadata Description of the audio that is suggested by the clients.
+     */
+    updateSinkMetadata(SinkMetadata sinkMetadata);
+
+    /**
+     * Set up required transports for receiving audio buffers from the driver.
+     *
+     * The transport consists of three message queues:
+     *  -- command queue is used to instruct the reader thread what operation
+     *     to perform;
+     *  -- data queue is used for passing audio data from the driver
+     *     to the client;
+     *  -- status queue is used for reporting operation status
+     *     (e.g. amount of bytes actually read or error code).
+     *
+     * The driver operates on a dedicated thread. The client must ensure that
+     * the thread is given an appropriate priority and assigned to correct
+     * scheduler and cgroup. For this purpose, the method returns identifiers
+     * of the driver thread.
+     *
+     * @param frameSize the size of a single frame, in bytes.
+     * @param framesCount the number of frames in a buffer.
+     * @param threadPriority priority of the driver thread.
+     * @return retval OK if both message queues were created successfully.
+     *                INVALID_STATE if the method was already called.
+     *                INVALID_ARGUMENTS if there was a problem setting up
+     *                                  the queues.
+     * @return commandMQ a message queue used for passing commands.
+     * @return dataMQ a message queue used for passing audio data in the format
+     *                specified at the stream opening.
+     * @return statusMQ a message queue used for passing status from the driver
+     *                  using ReadStatus structures.
+     * @return threadInfo identifiers of the driver's dedicated thread.
+     */
+    prepareForReading(uint32_t frameSize, uint32_t framesCount)
+    generates (
+            Result retval,
+            fmq_sync<ReadParameters> commandMQ,
+            fmq_sync<uint8_t> dataMQ,
+            fmq_sync<ReadStatus> statusMQ,
+            ThreadInfo threadInfo);
+
+    /**
+     * Return the amount of input frames lost in the audio driver since the last
+     * call of this function.
+     *
+     * Audio driver is expected to reset the value to 0 and restart counting
+     * upon returning the current value by this function call. Such loss
+     * typically occurs when the user space process is blocked longer than the
+     * capacity of audio driver buffers.
+     *
+     * @return framesLost the number of input audio frames lost.
+     */
+    getInputFramesLost() generates (uint32_t framesLost);
+
+    /**
+     * Return a recent count of the number of audio frames received and the
+     * clock time associated with that frame count.
+     *
+     * @return retval INVALID_STATE if the device is not ready/available,
+     *                NOT_SUPPORTED if the command is not supported,
+     *                OK otherwise.
+     * @return frames the total frame count received. This must be as early in
+     *                the capture pipeline as possible. In general, frames
+     *                must be non-negative and must not go "backwards".
+     * @return time is the clock monotonic time when frames was measured. In
+     *              general, time must be a positive quantity and must not
+     *              go "backwards".
+     */
+    getCapturePosition()
+            generates (Result retval, uint64_t frames, uint64_t time);
+
+    /**
+     * Returns an array with active microphones in the stream.
+     *
+     * @return retval INVALID_STATE if the call is not successful,
+     *                OK otherwise.
+     *
+     * @return microphones array with microphones info
+     */
+    getActiveMicrophones()
+               generates(Result retval, vec<MicrophoneInfo> microphones);
+};
diff --git a/audio/4.0/IStreamOut.hal b/audio/4.0/IStreamOut.hal
new file mode 100644
index 0000000..3aa93fc
--- /dev/null
+++ b/audio/4.0/IStreamOut.hal
@@ -0,0 +1,267 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+import IStream;
+import IStreamOutCallback;
+
+interface IStreamOut extends IStream {
+    /**
+     * Return the audio hardware driver estimated latency in milliseconds.
+     *
+     * @return latencyMs latency in milliseconds.
+     */
+    getLatency() generates (uint32_t latencyMs);
+
+    /**
+     * This method is used in situations where audio mixing is done in the
+     * hardware. This method serves as a direct interface with hardware,
+     * allowing to directly set the volume as apposed to via the framework.
+     * This method might produce multiple PCM outputs or hardware accelerated
+     * codecs, such as MP3 or AAC.
+     * Optional method
+     *
+     * @param left left channel attenuation, 1.0f is unity, 0.0f is zero.
+     * @param right right channel attenuation, 1.0f is unity, 0.0f is zero.
+     * @return retval operation completion status.
+     *        If a volume is outside [0,1], return INVALID_ARGUMENTS
+     */
+    setVolume(float left, float right) generates (Result retval);
+
+    /**
+     * Commands that can be executed on the driver writer thread.
+     */
+    enum WriteCommand : int32_t {
+        WRITE,
+        GET_PRESENTATION_POSITION,
+        GET_LATENCY
+    };
+
+    /**
+     * Data structure passed back to the client via status message queue
+     * of 'write' operation.
+     *
+     * Possible values of 'retval' field:
+     *  - OK, write operation was successful;
+     *  - INVALID_ARGUMENTS, stream was not configured properly;
+     *  - INVALID_STATE, stream is in a state that doesn't allow writes;
+     *  - INVALID_OPERATION, retrieving presentation position isn't supported.
+     */
+    struct WriteStatus {
+        Result retval;
+        WriteCommand replyTo;  // discriminator
+        union Reply {
+            uint64_t written;  // WRITE command, amount of bytes written, >= 0.
+            struct PresentationPosition {  // same as generated by
+                uint64_t frames;           // getPresentationPosition.
+                TimeSpec timeStamp;
+            } presentationPosition;
+            uint32_t latencyMs; // Same as generated by getLatency.
+        } reply;
+    };
+
+    /**
+     * Called when the metadata of the stream's source has been changed.
+     * @param sourceMetadata Description of the audio that is played by the clients.
+     */
+    updateSourceMetadata(SourceMetadata sourceMetadata);
+
+    /**
+     * Set up required transports for passing audio buffers to the driver.
+     *
+     * The transport consists of three message queues:
+     *  -- command queue is used to instruct the writer thread what operation
+     *     to perform;
+     *  -- data queue is used for passing audio data from the client
+     *     to the driver;
+     *  -- status queue is used for reporting operation status
+     *     (e.g. amount of bytes actually written or error code).
+     *
+     * The driver operates on a dedicated thread. The client must ensure that
+     * the thread is given an appropriate priority and assigned to correct
+     * scheduler and cgroup. For this purpose, the method returns identifiers
+     * of the driver thread.
+     *
+     * @param frameSize the size of a single frame, in bytes.
+     * @param framesCount the number of frames in a buffer.
+     * @return retval OK if both message queues were created successfully.
+     *                INVALID_STATE if the method was already called.
+     *                INVALID_ARGUMENTS if there was a problem setting up
+     *                                  the queues.
+     * @return commandMQ a message queue used for passing commands.
+     * @return dataMQ a message queue used for passing audio data in the format
+     *                specified at the stream opening.
+     * @return statusMQ a message queue used for passing status from the driver
+     *                  using WriteStatus structures.
+     * @return threadInfo identifiers of the driver's dedicated thread.
+     */
+    prepareForWriting(uint32_t frameSize, uint32_t framesCount)
+    generates (
+            Result retval,
+            fmq_sync<WriteCommand> commandMQ,
+            fmq_sync<uint8_t> dataMQ,
+            fmq_sync<WriteStatus> statusMQ,
+            ThreadInfo threadInfo);
+
+    /**
+     * Return the number of audio frames written by the audio DSP to DAC since
+     * the output has exited standby.
+     * Optional method
+     *
+     * @return retval operation completion status.
+     * @return dspFrames number of audio frames written.
+     */
+    getRenderPosition() generates (Result retval, uint32_t dspFrames);
+
+    /**
+     * Get the local time at which the next write to the audio driver will be
+     * presented. The units are microseconds, where the epoch is decided by the
+     * local audio HAL.
+     * Optional method
+     *
+     * @return retval operation completion status.
+     * @return timestampUs time of the next write.
+     */
+    getNextWriteTimestamp() generates (Result retval, int64_t timestampUs);
+
+    /**
+     * Set the callback interface for notifying completion of non-blocking
+     * write and drain.
+     *
+     * Calling this function implies that all future 'write' and 'drain'
+     * must be non-blocking and use the callback to signal completion.
+     *
+     * 'clearCallback' method needs to be called in order to release the local
+     * callback proxy on the server side and thus dereference the callback
+     * implementation on the client side.
+     *
+     * @return retval operation completion status.
+     */
+    setCallback(IStreamOutCallback callback) generates (Result retval);
+
+    /**
+     * Clears the callback previously set via 'setCallback' method.
+     *
+     * Warning: failure to call this method results in callback implementation
+     * on the client side being held until the HAL server termination.
+     *
+     * If no callback was previously set, the method should be a no-op
+     * and return OK.
+     *
+     * @return retval operation completion status: OK or NOT_SUPPORTED.
+     */
+    clearCallback() generates (Result retval);
+
+    /**
+     * Returns whether HAL supports pausing and resuming of streams.
+     *
+     * @return supportsPause true if pausing is supported.
+     * @return supportsResume true if resume is supported.
+     */
+    supportsPauseAndResume()
+            generates (bool supportsPause, bool supportsResume);
+
+    /**
+     * Notifies to the audio driver to stop playback however the queued buffers
+     * are retained by the hardware. Useful for implementing pause/resume. Empty
+     * implementation if not supported however must be implemented for hardware
+     * with non-trivial latency. In the pause state, some audio hardware may
+     * still be using power. Client code may consider calling 'suspend' after a
+     * timeout to prevent that excess power usage.
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     *
+     * @return retval operation completion status.
+     */
+    pause() generates (Result retval);
+
+    /**
+     * Notifies to the audio driver to resume playback following a pause.
+     * Returns error INVALID_STATE if called without matching pause.
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     *
+     * @return retval operation completion status.
+     */
+    resume() generates (Result retval);
+
+    /**
+     * Returns whether HAL supports draining of streams.
+     *
+     * @return supports true if draining is supported.
+     */
+    supportsDrain() generates (bool supports);
+
+    /**
+     * Requests notification when data buffered by the driver/hardware has been
+     * played. If 'setCallback' has previously been called to enable
+     * non-blocking mode, then 'drain' must not block, instead it must return
+     * quickly and completion of the drain is notified through the callback. If
+     * 'setCallback' has not been called, then 'drain' must block until
+     * completion.
+     *
+     * If 'type' is 'ALL', the drain completes when all previously written data
+     * has been played.
+     *
+     * If 'type' is 'EARLY_NOTIFY', the drain completes shortly before all data
+     * for the current track has played to allow time for the framework to
+     * perform a gapless track switch.
+     *
+     * Drain must return immediately on 'stop' and 'flush' calls.
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     *
+     * @param type type of drain.
+     * @return retval operation completion status.
+     */
+    drain(AudioDrain type) generates (Result retval);
+
+    /**
+     * Notifies to the audio driver to flush the queued data. Stream must
+     * already be paused before calling 'flush'.
+     * Optional method
+     *
+     * Implementation of this function is mandatory for offloaded playback.
+     *
+     * @return retval operation completion status.
+     */
+    flush() generates (Result retval);
+
+    /**
+     * Return a recent count of the number of audio frames presented to an
+     * external observer. This excludes frames which have been written but are
+     * still in the pipeline. The count is not reset to zero when output enters
+     * standby. Also returns the value of CLOCK_MONOTONIC as of this
+     * presentation count. The returned count is expected to be 'recent', but
+     * does not need to be the most recent possible value. However, the
+     * associated time must correspond to whatever count is returned.
+     *
+     * Example: assume that N+M frames have been presented, where M is a 'small'
+     * number. Then it is permissible to return N instead of N+M, and the
+     * timestamp must correspond to N rather than N+M. The terms 'recent' and
+     * 'small' are not defined. They reflect the quality of the implementation.
+     *
+     * Optional method
+     *
+     * @return retval operation completion status.
+     * @return frames count of presented audio frames.
+     * @return timeStamp associated clock time.
+     */
+    getPresentationPosition()
+            generates (Result retval, uint64_t frames, TimeSpec timeStamp);
+};
diff --git a/audio/4.0/IStreamOutCallback.hal b/audio/4.0/IStreamOutCallback.hal
new file mode 100644
index 0000000..9a19d32
--- /dev/null
+++ b/audio/4.0/IStreamOutCallback.hal
@@ -0,0 +1,37 @@
+/*
+ * 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.audio@4.0;
+
+/**
+ * Asynchronous write callback interface.
+ */
+interface IStreamOutCallback {
+    /**
+     * Non blocking write completed.
+     */
+    oneway onWriteReady();
+
+    /**
+     * Drain completed.
+     */
+    oneway onDrainReady();
+
+    /**
+     * Stream hit an error.
+     */
+    oneway onError();
+};
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..924fb47
--- /dev/null
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -0,0 +1,594 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the config versions supported by audio policy. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="halVersion">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Version of the interface the hal implements.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:decimal">
+            <!-- List of HAL versions supported by the framework. -->
+            <xs:enumeration value="2.0"/>
+            <xs:enumeration value="3.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="audioPolicyConfiguration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="globalConfiguration" type="globalConfiguration"/>
+                <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+                <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+            </xs:sequence>
+            <xs:attribute name="version" type="version"/>
+        </xs:complexType>
+        <xs:key name="moduleNameKey">
+            <xs:selector xpath="modules/module"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:unique name="volumeTargetUniqueness">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@stream"/>
+            <xs:field xpath="@deviceCategory"/>
+        </xs:unique>
+        <xs:key name="volumeCurveNameKey">
+            <xs:selector xpath="volumes/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@ref"/>
+        </xs:keyref>
+    </xs:element>
+    <xs:complexType name="globalConfiguration">
+        <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+    </xs:complexType>
+    <!-- Enum values of IDevicesFactory::Device
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="halName">
+        <xs:union>
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="primary"/>
+                    <xs:enumeration value="a2dp"/>
+                    <xs:enumeration value="usb"/>
+                    <xs:enumeration value="r_submix"/>
+                    <xs:enumeration value="codec_offload"/>
+                    <xs:enumeration value="stub"/>
+                </xs:restriction>
+            </xs:simpleType>
+            <xs:simpleType>
+                <xs:annotation>
+                    <xs:documentation xml:lang="en">
+                        Vendor eXtension names must be in the vx namespace.
+                        Vendor are encouraged to namespace their module names.
+                        Example for an hypothetical Google virtual reality HAL:
+                            <module name="vx_google_vr" halVersion="3.0"/>
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:restriction base="xs:string">
+                    <xs:pattern value="vx_[_a-zA-Z0-9]+"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:union>
+    </xs:simpleType>
+    <xs:complexType name="modules">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                There should be one section per audio HW module present on the platform.
+                Each <module/> contains two mandatory tags: “halVersion” and “name”.
+                The module "name" is the same as in previous .conf file.
+                Each module must contain the following sections:
+                 - <devicePorts/>: a list of device descriptors for all
+                   input and output devices accessible via this module.
+                   This contains both permanently attached devices and removable devices.
+                 - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+                 - <routes/>: list of possible connections between input
+                   and output devices or between stream and devices.
+                   A <route/> is defined by a set of 3 attributes:
+                        -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+                        -"sink": the sink involved in this route
+                        -"sources": all the sources than can be connected to the sink via this route
+                 - <attachedDevices/>: permanently attached devices.
+                   The attachedDevices section is a list of devices names.
+                   Their names correspond to device names defined in "devicePorts" section.
+                 - <defaultOutputDevice/> is the device to be used when no policy rule applies
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="module" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+                            <xs:unique name="attachedDevicesUniqueness">
+                                <xs:selector xpath="item"/>
+                                <xs:field xpath="."/>
+                            </xs:unique>
+                        </xs:element>
+                        <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+                        <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+                        <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+                        <xs:element name="routes" type="routes" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="halName" use="required"/>
+                    <xs:attribute name="halVersion" type="halVersion" use="required"/>
+                </xs:complexType>
+                <xs:unique name="mixPortNameUniqueness">
+                    <xs:selector xpath="mixPorts/mixPort"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+                <xs:key name="devicePortNameKey">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@tagName"/>
+                </xs:key>
+                <xs:unique name="devicePortUniqueness">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@type"/>
+                    <xs:field xpath="@address"/>
+                </xs:unique>
+                <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="defaultOutputDevice"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="attachedDevices/item"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <!-- The following 3 constraints try to make sure each sink port
+                     is reference in one an only one route. -->
+                <xs:key name="routeSinkKey">
+                    <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+                    <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+                    <xs:field xpath="@tagName|@name"/>
+                </xs:key>
+                <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:keyref>
+                <xs:unique name="routeUniqueness">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="attachedDevices">
+        <xs:sequence>
+            <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: separate values by space for better xsd validations. -->
+    <xs:simpleType name="audioInOutFlags">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                "|" separated list of audio_output_flags_t or audio_input_flags_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="role">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="sink"/>
+            <xs:enumeration value="source"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="mixPorts">
+        <xs:sequence>
+            <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="flags" type="audioInOutFlags"/>
+                    <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="preferredUsage" type="audioUsageList">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                When choosing the mixPort of an audio track, the audioPolicy
+                                first considers the mixPorts with a preferredUsage including
+                                the track AudioUsage preferred .
+                                If non support the track format, the other mixPorts are considered.
+                                Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+                                    the audio of all apps playing with a MEDIA usage.
+                                    It may receive audio from ALARM if there are no audio compatible
+                                    <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+                             </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="mixPortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="mixPortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- Enum values of audio_device_t in audio.h
+         TODO: generate from hidl to avoid manual sync.
+         TODO: separate source and sink in the xml for better xsd validations. -->
+    <xs:simpleType name="audioDevice">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+            <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ALL_USB"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+            <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+            <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ALL_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ALL_USB"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_format_t in audio.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="audioFormat">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+            <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+            <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+            <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+            <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+            <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio::common::4_0::AudioUsage
+         TODO: generate from HIDL to avoid manual sync. -->
+    <xs:simpleType name="audioUsage">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+            <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+            <xs:enumeration value="AUDIO_USAGE_ALARM" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_GAME" />
+            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioUsageList">
+        <xs:list itemType="audioUsage"/>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="samplingRates">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[0-9]+(,[0-9]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="channelMask">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma (",") separated list of channel flags
+                from audio_channel_mask_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="profile">
+        <xs:attribute name="name" type="xs:token" use="optional"/>
+        <xs:attribute name="format" type="audioFormat" use="optional"/>
+        <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+        <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
+    </xs:complexType>
+    <xs:simpleType name="gainMode">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="gains">
+        <xs:sequence>
+            <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="mode" type="gainMode" use="required"/>
+                    <xs:attribute name="channel_mask" type="channelMask" use="optional"/>
+                    <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="devicePorts">
+        <xs:sequence>
+            <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="tagName" type="xs:token" use="required"/>
+                    <xs:attribute name="type" type="audioDevice" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+                    <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+                    <xs:attribute name="default" type="xs:boolean" use="optional">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                The default device will be used if multiple have the same type
+                                and no explicit route request exists for a specific device of
+                                that type.
+                            </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="devicePortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="devicePortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="mixType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="mix"/>
+            <xs:enumeration value="mux"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="routes">
+        <xs:sequence>
+            <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation xml:lang="en">
+                        List all available sources for a given sink.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                    <xs:attribute name="type" type="mixType" use="required"/>
+                    <xs:attribute name="sink" type="xs:string" use="required"/>
+                    <xs:attribute name="sources" type="xs:string" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="volumes">
+        <xs:sequence>
+            <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: Always require a ref for better xsd validations.
+               Currently a volume could have no points nor ref
+               as it can not be forbidden by xsd 1.0.-->
+    <xs:simpleType name="volumePoint">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma separated pair of number.
+                The fist one is the framework level (between 0 and 100).
+                The second one is the volume to send to the HAL.
+                The framework will interpolate volumes not specified.
+                Their MUST be at least 2 points specified.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_stream_type_t in audio-base.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="stream">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+            <xs:enumeration value="AUDIO_STREAM_RING"/>
+            <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+            <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+            <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+            <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+            <xs:enumeration value="AUDIO_STREAM_TTS"/>
+            <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+            <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of device_category from Volume.h.
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="deviceCategory">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+            <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="volume">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Volume section defines a volume curve for a given use case and device category.
+                It contains a list of points of this curve expressing the attenuation in Millibels
+                for a given volume index from 0 to 100.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </volume>
+
+                It may also reference a reference/@name to avoid duplicating curves.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+                        ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+                <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </reference>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="stream" type="stream"/>
+        <xs:attribute name="deviceCategory" type="deviceCategory"/>
+        <xs:attribute name="ref" type="xs:token" use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="reference">
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+</xs:schema>
diff --git a/audio/4.0/types.hal b/audio/4.0/types.hal
new file mode 100644
index 0000000..7853f3c
--- /dev/null
+++ b/audio/4.0/types.hal
@@ -0,0 +1,275 @@
+/*
+ * 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.audio@4.0;
+
+import android.hardware.audio.common@4.0;
+
+enum Result : int32_t {
+    OK,
+    NOT_INITIALIZED,
+    INVALID_ARGUMENTS,
+    INVALID_STATE,
+    NOT_SUPPORTED
+};
+
+@export(name="audio_drain_type_t", value_prefix="AUDIO_DRAIN_")
+enum AudioDrain : int32_t {
+    /** drain() returns when all data has been played. */
+    ALL,
+    /**
+     * drain() returns a short time before all data from the current track has
+     * been played to give time for gapless track switch.
+     */
+    EARLY_NOTIFY
+};
+
+/**
+ * A substitute for POSIX timespec.
+ */
+struct TimeSpec {
+    uint64_t tvSec;   // seconds
+    uint64_t tvNSec;  // nanoseconds
+};
+
+/**
+ * IEEE 802 MAC address.
+ */
+typedef uint8_t[6] MacAddress;
+
+struct ParameterValue {
+    string key;
+    string value;
+};
+
+/**
+ * Specifies a device in case when several devices of the same type
+ * can be connected (e.g. BT A2DP, USB).
+ */
+struct DeviceAddress {
+    AudioDevice device;  // discriminator
+    union Address {
+        MacAddress mac;     // used for BLUETOOTH_A2DP_*
+        uint8_t[4] ipv4;    // used for IP
+        struct Alsa {
+            int32_t card;
+            int32_t device;
+        } alsa;             // used for USB_*
+    } address;
+    string busAddress;      // used for BUS
+    string rSubmixAddress;  // used for REMOTE_SUBMIX
+};
+
+enum MmapBufferFlag : uint32_t {
+    NONE    = 0x0,
+    /**
+     * If the buffer can be securely shared to untrusted applications
+     * through the AAudio exclusive mode.
+     * Only set this flag if applications are restricted from accessing the
+     * memory surrounding the audio data buffer by a kernel mechanism.
+     * See Linux kernel's dma_buf.
+     */
+    APPLICATION_SHAREABLE    = 0x1,
+};
+
+/**
+ * Mmap buffer descriptor returned by IStream.createMmapBuffer().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapBufferInfo {
+    /** Mmap memory buffer */
+    memory  sharedMemory;
+    /** Total buffer size in frames */
+    uint32_t bufferSizeFrames;
+    /** Transfer size granularity in frames */
+    uint32_t burstSizeFrames;
+    /** Attributes describing the buffer. */
+    bitfield<MmapBufferFlag> flags;
+};
+
+/**
+ * Mmap buffer read/write position returned by IStream.getMmapPosition().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapPosition {
+    int64_t  timeNanoseconds; // time stamp in ns, CLOCK_MONOTONIC
+    int32_t  positionFrames;  // increasing 32 bit frame count reset when IStream.stop() is called
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * message queues used by StreamIn and StreamOut.
+ */
+enum MessageQueueFlagBits : uint32_t {
+    NOT_EMPTY = 1 << 0,
+    NOT_FULL = 1 << 1
+};
+
+/** Metadata of a playback track for a StreamOut. */
+struct PlaybackTrackMetadata {
+    AudioUsage usage;
+    AudioContentType contentType;
+    /**
+     * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+     * 2 means double amplification...
+     * Must not be negative.
+     */
+    float gain;
+};
+
+/** Metadatas of the source of a StreamOut. */
+struct SourceMetadata {
+    vec<PlaybackTrackMetadata> tracks;
+};
+
+/** Metadata of a record track for a StreamIn. */
+struct RecordTrackMetadata {
+    AudioSource source;
+    /**
+     * Positive linear gain applied to the track samples. 0 being muted and 1 is no attenuation,
+     * 2 means double amplification...
+     * Must not be negative.
+     */
+    float gain;
+};
+
+/** Metadatas of the source of a StreamIn. */
+struct SinkMetadata {
+    vec<RecordTrackMetadata> tracks;
+};
+
+/*
+ * Microphone information
+ *
+ */
+
+/**
+ * A 3D point used to represent position or orientation of a microphone.
+ *
+ * Position: Coordinates of the microphone's capsule, in meters, from the
+ * bottom-left-back corner of the bounding box of android device in natural
+ * orientation (PORTRAIT for phones, LANDSCAPE for tablets, tvs, etc).
+ * The orientation musth match the reported by the api Display.getRotation().
+ *
+ * Orientation: Normalized vector to signal the main orientation of the
+ * microphone's capsule. Magnitude = sqrt(x^2 + y^2 + z^2) = 1
+ */
+struct AudioMicrophoneCoordinate {
+    float x;
+    float y;
+    float z;
+};
+
+/**
+ * Enum to identify the type of channel mapping for active microphones.
+ * Used channels further identify if the microphone has any significative
+ * process (e.g. High Pass Filtering, dynamic compression)
+ * Simple processing as constant gain adjustment must be DIRECT.
+ */
+enum AudioMicrophoneChannelMapping : uint32_t {
+    UNUSED      = 0, /** Channel not used */
+    DIRECT      = 1, /** Channel used and signal not processed */
+    PROCESSED   = 2, /** Channel used and signal has some process */
+};
+
+/**
+ * Enum to identify locations of microphones in regards to the body of the
+ * android device.
+ */
+enum AudioMicrophoneLocation : uint32_t {
+    UNKNOWN             = 0,
+    MAINBODY            = 1,
+    MAINBODY_MOVABLE    = 2,
+    PERIPHERAL          = 3,
+};
+
+/**
+ * Identifier to help group related microphones together
+ * e.g. microphone arrays should belong to the same group
+ */
+typedef int32_t AudioMicrophoneGroup;
+
+/**
+ * Enum with standard polar patterns of microphones
+ */
+enum AudioMicrophoneDirectionality : uint32_t {
+    UNKNOWN         = 0,
+    OMNI            = 1,
+    BI_DIRECTIONAL  = 2,
+    CARDIOID        = 3,
+    HYPER_CARDIOID  = 4,
+    SUPER_CARDIOID  = 5,
+};
+
+/**
+ * A (frequency, level) pair. Used to represent frequency response.
+ */
+struct AudioFrequencyResponsePoint {
+    /** In Hz */
+    float frequency;
+    /** In dB */
+    float level;
+};
+
+/**
+ * Structure used by the HAL to describe microphone's characteristics
+ * Used by StreamIn and Device
+ */
+struct MicrophoneInfo {
+    /** Unique alphanumeric id for microphone. Guaranteed to be the same
+     * even after rebooting.
+     */
+    string                                  deviceId;
+    /**
+     * Device specific information
+     */
+    DeviceAddress                           deviceAddress;
+    /** Each element of the vector must describe the channel with the same
+     *  index.
+     */
+    vec<AudioMicrophoneChannelMapping>      channelMapping;
+    /** Location of the microphone in regard to the body of the device */
+    AudioMicrophoneLocation                 location;
+    /** Identifier to help group related microphones together
+     *  e.g. microphone arrays should belong to the same group
+     */
+    AudioMicrophoneGroup                    group;
+    /** Index of this microphone within the group.
+     *  (group, index) must be unique within the same device.
+     */
+    uint32_t                                indexInTheGroup;
+    /** Level in dBFS produced by a 1000 Hz tone at 94 dB SPL */
+    float                                   sensitivity;
+    /** Level in dB of the max SPL supported at 1000 Hz */
+    float                                   maxSpl;
+    /** Level in dB of the min SPL supported at 1000 Hz */
+    float                                   minSpl;
+    /** Standard polar pattern of the microphone */
+    AudioMicrophoneDirectionality           directionality;
+    /** Vector with ordered frequency responses (from low to high frequencies)
+     *  with the frequency response of the microphone.
+     *  Levels are in dB, relative to level at 1000 Hz
+     */
+    vec<AudioFrequencyResponsePoint>        frequencyResponse;
+    /** Position of the microphone's capsule in meters, from the
+     *  bottom-left-back corner of the bounding box of device.
+     */
+    AudioMicrophoneCoordinate               position;
+    /** Normalized point to signal the main orientation of the microphone's
+     *  capsule. sqrt(x^2 + y^2 + z^2) = 1
+     */
+    AudioMicrophoneCoordinate               orientation;
+};
diff --git a/audio/README b/audio/README
index 2b81450..1f1e8e3 100644
--- a/audio/README
+++ b/audio/README
@@ -1,8 +1,9 @@
 Directory structure of the audio HIDL related code.
 
 audio
-|-- 2.0              <== legacy 2.0 core HIDL (.hal) can not be moved to fit
-|                        the directory structure because already published
+|-- 2.0              <== HIDL (.hal) can not be moved to fit the directory structure
+|                        because that would create a separate HAL
+|-- 4.0              <== Version 4.0 of the core API
 |
 |-- common           <== code common to audio core and effect API
 |   |-- 2.0
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
new file mode 100644
index 0000000..9b737dc
--- /dev/null
+++ b/audio/common/4.0/Android.bp
@@ -0,0 +1,48 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.audio.common@4.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    types: [
+        "AudioChannelMask",
+        "AudioConfig",
+        "AudioContentType",
+        "AudioDevice",
+        "AudioFormat",
+        "AudioGain",
+        "AudioGainConfig",
+        "AudioGainMode",
+        "AudioHandleConsts",
+        "AudioInputFlag",
+        "AudioMixLatencyClass",
+        "AudioMode",
+        "AudioOffloadInfo",
+        "AudioOutputFlag",
+        "AudioPort",
+        "AudioPortConfig",
+        "AudioPortConfigDeviceExt",
+        "AudioPortConfigMask",
+        "AudioPortConfigSessionExt",
+        "AudioPortDeviceExt",
+        "AudioPortMixExt",
+        "AudioPortRole",
+        "AudioPortSessionExt",
+        "AudioPortType",
+        "AudioSessionConsts",
+        "AudioSource",
+        "AudioStreamType",
+        "AudioUsage",
+        "FixedChannelCount",
+        "ThreadInfo",
+        "Uuid",
+    ],
+    gen_java: false,
+    gen_java_constants: true,
+}
+
diff --git a/audio/common/4.0/types.hal b/audio/common/4.0/types.hal
new file mode 100644
index 0000000..d4c6efe
--- /dev/null
+++ b/audio/common/4.0/types.hal
@@ -0,0 +1,888 @@
+/*
+ * 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.audio.common@4.0;
+
+/*
+ *
+ *  IDs and Handles
+ *
+ */
+
+/**
+ * Handle type for identifying audio sources and sinks.
+ */
+typedef int32_t AudioIoHandle;
+
+/**
+ * Audio hw module handle functions or structures referencing a module.
+ */
+typedef int32_t AudioModuleHandle;
+
+/**
+ * Each port has a unique ID or handle allocated by policy manager.
+ */
+typedef int32_t AudioPortHandle;
+
+/**
+ * Each patch is identified by a handle at the interface used to create that
+ * patch. For instance, when a patch is created by the audio HAL, the HAL
+ * allocates and returns a handle.  This handle is unique to a given audio HAL
+ * hardware module.  But the same patch receives another system wide unique
+ * handle allocated by the framework.  This unique handle is used for all
+ * transactions inside the framework.
+ */
+typedef int32_t AudioPatchHandle;
+
+/**
+ * A HW synchronization source returned by the audio HAL.
+ */
+typedef uint32_t AudioHwSync;
+
+/**
+ * Each port has a unique ID or handle allocated by policy manager.
+ */
+@export(name="")
+enum AudioHandleConsts : int32_t {
+    AUDIO_IO_HANDLE_NONE = 0,
+    AUDIO_MODULE_HANDLE_NONE = 0,
+    AUDIO_PORT_HANDLE_NONE = 0,
+    AUDIO_PATCH_HANDLE_NONE = 0,
+};
+
+/**
+ * Commonly used structure for passing unique identifieds (UUID).
+ * For the definition of UUID, refer to ITU-T X.667 spec.
+ */
+struct Uuid {
+    uint32_t timeLow;
+    uint16_t timeMid;
+    uint16_t versionAndTimeHigh;
+    uint16_t variantAndClockSeqHigh;
+    uint8_t[6] node;
+};
+
+
+/*
+ *
+ *  Audio streams
+ *
+ */
+
+/**
+ * Audio stream type describing the intended use case of a stream.
+ */
+@export(name="audio_stream_type_t", value_prefix="AUDIO_STREAM_")
+enum AudioStreamType : int32_t {
+    // These values must kept in sync with
+    //  frameworks/base/media/java/android/media/AudioSystem.java
+    DEFAULT          = -1,
+    MIN              = 0,
+    VOICE_CALL       = 0,
+    SYSTEM           = 1,
+    RING             = 2,
+    MUSIC            = 3,
+    ALARM            = 4,
+    NOTIFICATION     = 5,
+    BLUETOOTH_SCO    = 6,
+    ENFORCED_AUDIBLE = 7,  // Sounds that cannot be muted by user and must be
+                           // routed to speaker
+    DTMF             = 8,
+    TTS              = 9,  // Transmitted Through Speaker.  Plays over speaker
+                           // only, silent on other devices
+    ACCESSIBILITY    = 10, // For accessibility talk back prompts
+    REROUTING        = 11, // For dynamic policy output mixes
+    PATCH            = 12, // For internal audio flinger tracks.  Fixed volume
+};
+
+@export(name="audio_source_t", value_prefix="AUDIO_SOURCE_")
+enum AudioSource : int32_t {
+    // These values must kept in sync with
+    //  frameworks/base/media/java/android/media/MediaRecorder.java,
+    //  frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
+    //  system/media/audio_effects/include/audio_effects/audio_effects_conf.h
+    DEFAULT             = 0,
+    MIC                 = 1,
+    VOICE_UPLINK        = 2,
+    VOICE_DOWNLINK      = 3,
+    VOICE_CALL          = 4,
+    CAMCORDER           = 5,
+    VOICE_RECOGNITION   = 6,
+    VOICE_COMMUNICATION = 7,
+    /**
+     * Source for the mix to be presented remotely. An example of remote
+     * presentation is Wifi Display where a dongle attached to a TV can be used
+     * to play the mix captured by this audio source.
+     */
+    REMOTE_SUBMIX       = 8,
+    /**
+     * Source for unprocessed sound. Usage examples include level measurement
+     * and raw signal analysis.
+     */
+    UNPROCESSED         = 9,
+
+    FM_TUNER            = 1998,
+};
+
+typedef int32_t AudioSession;
+/**
+ * Special audio session values.
+ */
+@export(name="audio_session_t", value_prefix="AUDIO_SESSION_")
+enum AudioSessionConsts : int32_t {
+    /**
+     * Session for effects attached to a particular output stream
+     * (value must be less than 0)
+     */
+    OUTPUT_STAGE = -1,
+    /**
+     * Session for effects applied to output mix. These effects can
+     * be moved by audio policy manager to another output stream
+     * (value must be 0)
+     */
+    OUTPUT_MIX = 0,
+    /**
+     * Application does not specify an explicit session ID to be used, and
+     * requests a new session ID to be allocated. Corresponds to
+     * AudioManager.AUDIO_SESSION_ID_GENERATE and
+     * AudioSystem.AUDIO_SESSION_ALLOCATE.
+     */
+    ALLOCATE = 0,
+    /**
+     * For use with AudioRecord::start(), this indicates no trigger session.
+     * It is also used with output tracks and patch tracks, which never have a
+     * session.
+     */
+    NONE = 0
+};
+
+/**
+ * Audio format  is a 32-bit word that consists of:
+ *   main format field (upper 8 bits)
+ *   sub format field (lower 24 bits).
+ *
+ * The main format indicates the main codec type. The sub format field indicates
+ * options and parameters for each format. The sub format is mainly used for
+ * record to indicate for instance the requested bitrate or profile.  It can
+ * also be used for certain formats to give informations not present in the
+ * encoded audio stream (e.g. octet alignement for AMR).
+ */
+@export(name="audio_format_t", value_prefix="AUDIO_FORMAT_")
+enum AudioFormat : uint32_t {
+    INVALID             = 0xFFFFFFFFUL,
+    DEFAULT             = 0,
+    PCM                 = 0x00000000UL,
+    MP3                 = 0x01000000UL,
+    AMR_NB              = 0x02000000UL,
+    AMR_WB              = 0x03000000UL,
+    AAC                 = 0x04000000UL,
+    /** Deprecated, Use AAC_HE_V1 */
+    HE_AAC_V1           = 0x05000000UL,
+    /** Deprecated, Use AAC_HE_V2 */
+    HE_AAC_V2           = 0x06000000UL,
+    VORBIS              = 0x07000000UL,
+    OPUS                = 0x08000000UL,
+    AC3                 = 0x09000000UL,
+    E_AC3               = 0x0A000000UL,
+    DTS                 = 0x0B000000UL,
+    DTS_HD              = 0x0C000000UL,
+    /** IEC61937 is encoded audio wrapped in 16-bit PCM. */
+    IEC61937            = 0x0D000000UL,
+    DOLBY_TRUEHD        = 0x0E000000UL,
+    EVRC                = 0x10000000UL,
+    EVRCB               = 0x11000000UL,
+    EVRCWB              = 0x12000000UL,
+    EVRCNW              = 0x13000000UL,
+    AAC_ADIF            = 0x14000000UL,
+    WMA                 = 0x15000000UL,
+    WMA_PRO             = 0x16000000UL,
+    AMR_WB_PLUS         = 0x17000000UL,
+    MP2                 = 0x18000000UL,
+    QCELP               = 0x19000000UL,
+    DSD                 = 0x1A000000UL,
+    FLAC                = 0x1B000000UL,
+    ALAC                = 0x1C000000UL,
+    APE                 = 0x1D000000UL,
+    AAC_ADTS            = 0x1E000000UL,
+    SBC                 = 0x1F000000UL,
+    APTX                = 0x20000000UL,
+    APTX_HD             = 0x21000000UL,
+    AC4                 = 0x22000000UL,
+    LDAC                = 0x23000000UL,
+    /** Dolby Metadata-enhanced Audio Transmission */
+    MAT                 = 0x24000000UL,
+    /** Deprecated */
+    MAIN_MASK           = 0xFF000000UL,
+    SUB_MASK            = 0x00FFFFFFUL,
+
+    /* Subformats */
+    PCM_SUB_16_BIT        = 0x1, // PCM signed 16 bits
+    PCM_SUB_8_BIT         = 0x2, // PCM unsigned 8 bits
+    PCM_SUB_32_BIT        = 0x3, // PCM signed .31 fixed point
+    PCM_SUB_8_24_BIT      = 0x4, // PCM signed 8.23 fixed point
+    PCM_SUB_FLOAT         = 0x5, // PCM single-precision float pt
+    PCM_SUB_24_BIT_PACKED = 0x6, // PCM signed .23 fix pt (3 bytes)
+
+    MP3_SUB_NONE          = 0x0,
+
+    AMR_SUB_NONE          = 0x0,
+
+    AAC_SUB_MAIN          = 0x1,
+    AAC_SUB_LC            = 0x2,
+    AAC_SUB_SSR           = 0x4,
+    AAC_SUB_LTP           = 0x8,
+    AAC_SUB_HE_V1         = 0x10,
+    AAC_SUB_SCALABLE      = 0x20,
+    AAC_SUB_ERLC          = 0x40,
+    AAC_SUB_LD            = 0x80,
+    AAC_SUB_HE_V2         = 0x100,
+    AAC_SUB_ELD           = 0x200,
+    AAC_SUB_XHE           = 0x300,
+
+    VORBIS_SUB_NONE       = 0x0,
+
+    E_AC3_SUB_JOC         = 0x1,
+
+    MAT_SUB_1_0           = 0x1,
+    MAT_SUB_2_0           = 0x2,
+    MAT_SUB_2_1           = 0x3,
+
+    /* Aliases */
+    /** note != AudioFormat.ENCODING_PCM_16BIT */
+    PCM_16_BIT          = (PCM | PCM_SUB_16_BIT),
+    /** note != AudioFormat.ENCODING_PCM_8BIT */
+    PCM_8_BIT           = (PCM | PCM_SUB_8_BIT),
+    PCM_32_BIT          = (PCM | PCM_SUB_32_BIT),
+    PCM_8_24_BIT        = (PCM | PCM_SUB_8_24_BIT),
+    PCM_FLOAT           = (PCM | PCM_SUB_FLOAT),
+    PCM_24_BIT_PACKED   = (PCM | PCM_SUB_24_BIT_PACKED),
+    AAC_MAIN            = (AAC | AAC_SUB_MAIN),
+    AAC_LC              = (AAC | AAC_SUB_LC),
+    AAC_SSR             = (AAC | AAC_SUB_SSR),
+    AAC_LTP             = (AAC | AAC_SUB_LTP),
+    AAC_HE_V1           = (AAC | AAC_SUB_HE_V1),
+    AAC_SCALABLE        = (AAC | AAC_SUB_SCALABLE),
+    AAC_ERLC            = (AAC | AAC_SUB_ERLC),
+    AAC_LD              = (AAC | AAC_SUB_LD),
+    AAC_HE_V2           = (AAC | AAC_SUB_HE_V2),
+    AAC_ELD             = (AAC | AAC_SUB_ELD),
+    AAC_XHE             = (AAC | AAC_SUB_XHE),
+    AAC_ADTS_MAIN       = (AAC_ADTS | AAC_SUB_MAIN),
+    AAC_ADTS_LC         = (AAC_ADTS | AAC_SUB_LC),
+    AAC_ADTS_SSR        = (AAC_ADTS | AAC_SUB_SSR),
+    AAC_ADTS_LTP        = (AAC_ADTS | AAC_SUB_LTP),
+    AAC_ADTS_HE_V1      = (AAC_ADTS | AAC_SUB_HE_V1),
+    AAC_ADTS_SCALABLE   = (AAC_ADTS | AAC_SUB_SCALABLE),
+    AAC_ADTS_ERLC       = (AAC_ADTS | AAC_SUB_ERLC),
+    AAC_ADTS_LD         = (AAC_ADTS | AAC_SUB_LD),
+    AAC_ADTS_HE_V2      = (AAC_ADTS | AAC_SUB_HE_V2),
+    AAC_ADTS_ELD        = (AAC_ADTS | AAC_SUB_ELD),
+    AAC_ADTS_XHE        = (AAC_ADTS | AAC_SUB_XHE),
+    E_AC3_JOC           = (E_AC3 | E_AC3_SUB_JOC),
+    MAT_1_0             = (MAT | MAT_SUB_1_0),
+    MAT_2_0             = (MAT | MAT_SUB_2_0),
+    MAT_2_1             = (MAT | MAT_SUB_2_1),
+};
+
+/**
+ * Usage of these values highlights places in the code that use 2- or 8- channel
+ * assumptions.
+ */
+@export(name="")
+enum FixedChannelCount : int32_t {
+    FCC_2 = 2, // This is typically due to legacy implementation of stereo I/O
+    FCC_8 = 8  // This is typically due to audio mixer and resampler limitations
+};
+
+/**
+ * A channel mask per se only defines the presence or absence of a channel, not
+ * the order.  See AUDIO_INTERLEAVE_* for the platform convention of order.
+ *
+ * AudioChannelMask is an opaque type and its internal layout should not be
+ * assumed as it may change in the future.  Instead, always use functions
+ * to examine it.
+ *
+ * These are the current representations:
+ *
+ *   REPRESENTATION_POSITION
+ *     is a channel mask representation for position assignment.  Each low-order
+ *     bit corresponds to the spatial position of a transducer (output), or
+ *     interpretation of channel (input).  The user of a channel mask needs to
+ *     know the context of whether it is for output or input.  The constants
+ *     OUT_* or IN_* apply to the bits portion.  It is not permitted for no bits
+ *     to be set.
+ *
+ *   REPRESENTATION_INDEX
+ *     is a channel mask representation for index assignment.  Each low-order
+ *     bit corresponds to a selected channel.  There is no platform
+ *     interpretation of the various bits.  There is no concept of output or
+ *     input.  It is not permitted for no bits to be set.
+ *
+ * All other representations are reserved for future use.
+ *
+ * Warning: current representation distinguishes between input and output, but
+ * this will not the be case in future revisions of the platform. Wherever there
+ * is an ambiguity between input and output that is currently resolved by
+ * checking the channel mask, the implementer should look for ways to fix it
+ * with additional information outside of the mask.
+ */
+@export(name="", value_prefix="AUDIO_CHANNEL_")
+enum AudioChannelMask : uint32_t {
+    /** must be 0 for compatibility */
+    REPRESENTATION_POSITION = 0,
+    /** 1 is reserved for future use */
+    REPRESENTATION_INDEX    = 2,
+    /* 3 is reserved for future use */
+
+    /** These can be a complete value of AudioChannelMask */
+    NONE                      = 0x0,
+    INVALID                   = 0xC0000000,
+
+   /*
+    * These can be the bits portion of an AudioChannelMask
+    * with representation REPRESENTATION_POSITION.
+    */
+
+    /** output channels */
+    OUT_FRONT_LEFT            = 0x1,
+    OUT_FRONT_RIGHT           = 0x2,
+    OUT_FRONT_CENTER          = 0x4,
+    OUT_LOW_FREQUENCY         = 0x8,
+    OUT_BACK_LEFT             = 0x10,
+    OUT_BACK_RIGHT            = 0x20,
+    OUT_FRONT_LEFT_OF_CENTER  = 0x40,
+    OUT_FRONT_RIGHT_OF_CENTER = 0x80,
+    OUT_BACK_CENTER           = 0x100,
+    OUT_SIDE_LEFT             = 0x200,
+    OUT_SIDE_RIGHT            = 0x400,
+    OUT_TOP_CENTER            = 0x800,
+    OUT_TOP_FRONT_LEFT        = 0x1000,
+    OUT_TOP_FRONT_CENTER      = 0x2000,
+    OUT_TOP_FRONT_RIGHT       = 0x4000,
+    OUT_TOP_BACK_LEFT         = 0x8000,
+    OUT_TOP_BACK_CENTER       = 0x10000,
+    OUT_TOP_BACK_RIGHT        = 0x20000,
+    OUT_TOP_CENTER_LEFT       = 0x40000,
+    OUT_TOP_CENTER_RIGHT      = 0x80000,
+
+    OUT_MONO     = OUT_FRONT_LEFT,
+    OUT_STEREO   = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT),
+    OUT_2POINT1  = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT | OUT_LOW_FREQUENCY),
+    OUT_2POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+    OUT_2POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+                         OUT_LOW_FREQUENCY),
+    OUT_3POINT0POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+                         OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT),
+    OUT_3POINT1POINT2 = (OUT_FRONT_LEFT | OUT_FRONT_CENTER | OUT_FRONT_RIGHT |
+                        OUT_TOP_CENTER_LEFT | OUT_TOP_CENTER_RIGHT |
+                        OUT_LOW_FREQUENCY),
+    OUT_QUAD     = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_BACK_LEFT | OUT_BACK_RIGHT),
+    OUT_QUAD_BACK = OUT_QUAD,
+    /** like OUT_QUAD_BACK with *_SIDE_* instead of *_BACK_* */
+    OUT_QUAD_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+    OUT_SURROUND = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_BACK_CENTER),
+    OUT_PENTA = (OUT_QUAD | OUT_FRONT_CENTER),
+    OUT_5POINT1   = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+            OUT_BACK_LEFT | OUT_BACK_RIGHT),
+    OUT_5POINT1_BACK = OUT_5POINT1,
+    /** like OUT_5POINT1_BACK with *_SIDE_* instead of *_BACK_* */
+    OUT_5POINT1_SIDE = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+            OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+    OUT_6POINT1 = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+            OUT_BACK_LEFT | OUT_BACK_RIGHT |
+            OUT_BACK_CENTER),
+    /** matches the correct AudioFormat.CHANNEL_OUT_7POINT1_SURROUND */
+    OUT_7POINT1  = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+            OUT_BACK_LEFT | OUT_BACK_RIGHT |
+            OUT_SIDE_LEFT | OUT_SIDE_RIGHT),
+    // Note that the 2.0 OUT_ALL* have been moved to helper functions
+
+    /* These are bits only, not complete values */
+
+    /** input channels */
+    IN_LEFT            = 0x4,
+    IN_RIGHT           = 0x8,
+    IN_FRONT           = 0x10,
+    IN_BACK            = 0x20,
+    IN_LEFT_PROCESSED  = 0x40,
+    IN_RIGHT_PROCESSED = 0x80,
+    IN_FRONT_PROCESSED = 0x100,
+    IN_BACK_PROCESSED  = 0x200,
+    IN_PRESSURE        = 0x400,
+    IN_X_AXIS          = 0x800,
+    IN_Y_AXIS          = 0x1000,
+    IN_Z_AXIS          = 0x2000,
+    IN_BACK_LEFT       = 0x10000,
+    IN_BACK_RIGHT      = 0x20000,
+    IN_CENTER          = 0x40000,
+    IN_LOW_FREQUENCY   = 0x100000,
+    IN_TOP_LEFT        = 0x200000,
+    IN_TOP_RIGHT       = 0x400000,
+
+    IN_VOICE_UPLINK    = 0x4000,
+    IN_VOICE_DNLINK    = 0x8000,
+
+    IN_MONO   = IN_FRONT,
+    IN_STEREO = (IN_LEFT | IN_RIGHT),
+    IN_FRONT_BACK = (IN_FRONT | IN_BACK),
+    IN_6 = (IN_LEFT | IN_RIGHT |
+            IN_FRONT | IN_BACK |
+            IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED),
+    IN_5POINT1 = (IN_LEFT | IN_CENTER | IN_RIGHT |
+                  IN_BACK_LEFT | IN_BACK_RIGHT | IN_LOW_FREQUENCY),
+    IN_VOICE_UPLINK_MONO = (IN_VOICE_UPLINK | IN_MONO),
+    IN_VOICE_DNLINK_MONO = (IN_VOICE_DNLINK | IN_MONO),
+    IN_VOICE_CALL_MONO   = (IN_VOICE_UPLINK_MONO |
+            IN_VOICE_DNLINK_MONO),
+    // Note that the 2.0 IN_ALL* have been moved to helper functions
+
+    COUNT_MAX    = 30,
+    INDEX_HDR    = REPRESENTATION_INDEX << COUNT_MAX,
+    INDEX_MASK_1 = INDEX_HDR | ((1 << 1) - 1),
+    INDEX_MASK_2 = INDEX_HDR | ((1 << 2) - 1),
+    INDEX_MASK_3 = INDEX_HDR | ((1 << 3) - 1),
+    INDEX_MASK_4 = INDEX_HDR | ((1 << 4) - 1),
+    INDEX_MASK_5 = INDEX_HDR | ((1 << 5) - 1),
+    INDEX_MASK_6 = INDEX_HDR | ((1 << 6) - 1),
+    INDEX_MASK_7 = INDEX_HDR | ((1 << 7) - 1),
+    INDEX_MASK_8 = INDEX_HDR | ((1 << 8) - 1)
+};
+
+/**
+ * Major modes for a mobile device. The current mode setting affects audio
+ * routing.
+ */
+@export(name="audio_mode_t", value_prefix="AUDIO_MODE_")
+enum AudioMode : int32_t {
+    NORMAL           = 0,
+    RINGTONE         = 1,
+    /** Calls handled by the telephony stack (Eg: PSTN). */
+    IN_CALL          = 2,
+    /** Calls handled by apps (Eg: Hangout). */
+    IN_COMMUNICATION = 3,
+};
+
+@export(name="", value_prefix="AUDIO_DEVICE_")
+enum AudioDevice : uint64_t {
+    NONE                          = 0x0,
+    /** reserved bits */
+    BIT_IN                        = 0x80000000,
+    BIT_DEFAULT                   = 0x40000000,
+    /** output devices */
+    OUT_EARPIECE                  = 0x1,
+    OUT_SPEAKER                   = 0x2,
+    OUT_WIRED_HEADSET             = 0x4,
+    OUT_WIRED_HEADPHONE           = 0x8,
+    OUT_BLUETOOTH_SCO             = 0x10,
+    OUT_BLUETOOTH_SCO_HEADSET     = 0x20,
+    OUT_BLUETOOTH_SCO_CARKIT      = 0x40,
+    OUT_BLUETOOTH_A2DP            = 0x80,
+    OUT_BLUETOOTH_A2DP_HEADPHONES = 0x100,
+    OUT_BLUETOOTH_A2DP_SPEAKER    = 0x200,
+    OUT_AUX_DIGITAL               = 0x400,
+    OUT_HDMI                      = OUT_AUX_DIGITAL,
+    /** uses an analog connection (multiplexed over the USB pins for instance) */
+    OUT_ANLG_DOCK_HEADSET         = 0x800,
+    OUT_DGTL_DOCK_HEADSET         = 0x1000,
+    /** USB accessory mode: Android device is USB device and dock is USB host */
+    OUT_USB_ACCESSORY             = 0x2000,
+    /** USB host mode: Android device is USB host and dock is USB device */
+    OUT_USB_DEVICE                = 0x4000,
+    OUT_REMOTE_SUBMIX             = 0x8000,
+    /** Telephony voice TX path */
+    OUT_TELEPHONY_TX              = 0x10000,
+    /** Analog jack with line impedance detected */
+    OUT_LINE                      = 0x20000,
+    /** HDMI Audio Return Channel */
+    OUT_HDMI_ARC                  = 0x40000,
+    /** S/PDIF out */
+    OUT_SPDIF                     = 0x80000,
+    /** FM transmitter out */
+    OUT_FM                        = 0x100000,
+    /** Line out for av devices */
+    OUT_AUX_LINE                  = 0x200000,
+    /** limited-output speaker device for acoustic safety */
+    OUT_SPEAKER_SAFE              = 0x400000,
+    OUT_IP                        = 0x800000,
+    /** audio bus implemented by the audio system (e.g an MOST stereo channel) */
+    OUT_BUS                       = 0x1000000,
+    OUT_PROXY                     = 0x2000000,
+    OUT_USB_HEADSET               = 0x4000000,
+    OUT_ECHO_CANCELLER            = 0x10000000,
+    OUT_DEFAULT                   = BIT_DEFAULT,
+    // Note that the 2.0 OUT_ALL* have been moved to helper functions
+
+    /** input devices */
+    IN_COMMUNICATION         = BIT_IN | 0x1,
+    IN_AMBIENT               = BIT_IN | 0x2,
+    IN_BUILTIN_MIC           = BIT_IN | 0x4,
+    IN_BLUETOOTH_SCO_HEADSET = BIT_IN | 0x8,
+    IN_WIRED_HEADSET         = BIT_IN | 0x10,
+    IN_AUX_DIGITAL           = BIT_IN | 0x20,
+    IN_HDMI                  = IN_AUX_DIGITAL,
+    /** Telephony voice RX path */
+    IN_VOICE_CALL            = BIT_IN | 0x40,
+    IN_TELEPHONY_RX          = IN_VOICE_CALL,
+    IN_BACK_MIC              = BIT_IN | 0x80,
+    IN_REMOTE_SUBMIX         = BIT_IN | 0x100,
+    IN_ANLG_DOCK_HEADSET     = BIT_IN | 0x200,
+    IN_DGTL_DOCK_HEADSET     = BIT_IN | 0x400,
+    IN_USB_ACCESSORY         = BIT_IN | 0x800,
+    IN_USB_DEVICE            = BIT_IN | 0x1000,
+    /** FM tuner input */
+    IN_FM_TUNER              = BIT_IN | 0x2000,
+    /** TV tuner input */
+    IN_TV_TUNER              = BIT_IN | 0x4000,
+    /** Analog jack with line impedance detected */
+    IN_LINE                  = BIT_IN | 0x8000,
+    /** S/PDIF in */
+    IN_SPDIF                 = BIT_IN | 0x10000,
+    IN_BLUETOOTH_A2DP        = BIT_IN | 0x20000,
+    IN_LOOPBACK              = BIT_IN | 0x40000,
+    IN_IP                    = BIT_IN | 0x80000,
+    /** audio bus implemented by the audio system (e.g an MOST stereo channel) */
+    IN_BUS                   = BIT_IN | 0x100000,
+    IN_PROXY                 = BIT_IN | 0x1000000,
+    IN_USB_HEADSET           = BIT_IN | 0x2000000,
+    IN_BLUETOOTH_BLE         = BIT_IN | 0x4000000,
+    IN_DEFAULT               = BIT_IN | BIT_DEFAULT,
+
+    // Note that the 2.0 IN_ALL* have been moved to helper functions
+};
+
+/**
+ * The audio output flags serve two purposes:
+ *
+ *  - when an AudioTrack is created they indicate a "wish" to be connected to an
+ *    output stream with attributes corresponding to the specified flags;
+ *
+ *  - when present in an output profile descriptor listed for a particular audio
+ *    hardware module, they indicate that an output stream can be opened that
+ *    supports the attributes indicated by the flags.
+ *
+ * The audio policy manager will try to match the flags in the request
+ * (when getOuput() is called) to an available output stream.
+ */
+@export(name="audio_output_flags_t", value_prefix="AUDIO_OUTPUT_FLAG_")
+enum AudioOutputFlag : int32_t {
+    NONE    = 0x0, // no attributes
+    DIRECT  = 0x1, // this output directly connects a track
+                   // to one output stream: no software mixer
+    PRIMARY = 0x2, // this output is the primary output of the device. It is
+                   // unique and must be present. It is opened by default and
+                   // receives routing, audio mode and volume controls related
+                   // to voice calls.
+    FAST    = 0x4,    // output supports "fast tracks", defined elsewhere
+    DEEP_BUFFER      = 0x8,   // use deep audio buffers
+    COMPRESS_OFFLOAD = 0x10,  // offload playback of compressed streams to
+                              // hardware codec
+    NON_BLOCKING     = 0x20,  // use non-blocking write
+    HW_AV_SYNC = 0x40,   // output uses a hardware A/V sync
+    TTS        = 0x80,   // output for streams transmitted through speaker at a
+                         // sample rate high enough to accommodate lower-range
+                         // ultrasonic p/b
+    RAW        = 0x100,  // minimize signal processing
+    SYNC       = 0x200,  // synchronize I/O streams
+    IEC958_NONAUDIO = 0x400, // Audio stream contains compressed audio in SPDIF
+                             // data bursts, not PCM.
+    DIRECT_PCM = 0x2000,     // Audio stream containing PCM data that needs
+                             // to pass through compress path for DSP post proc.
+    MMAP_NOIRQ = 0x4000, // output operates in MMAP no IRQ mode.
+    VOIP_RX = 0x8000,    // preferred output for VoIP calls.
+    /** preferred output for call music */
+    INCALL_MUSIC = 0x10000,
+};
+
+/**
+ * The audio input flags are analogous to audio output flags.
+ * Currently they are used only when an AudioRecord is created,
+ * to indicate a preference to be connected to an input stream with
+ * attributes corresponding to the specified flags.
+ */
+@export(name="audio_input_flags_t", value_prefix="AUDIO_INPUT_FLAG_")
+enum AudioInputFlag : int32_t {
+    NONE         = 0x0,  // no attributes
+    FAST         = 0x1,  // prefer an input that supports "fast tracks"
+    HW_HOTWORD   = 0x2,  // prefer an input that captures from hw hotword source
+    RAW          = 0x4,  // minimize signal processing
+    SYNC         = 0x8,  // synchronize I/O streams
+    MMAP_NOIRQ   = 0x10, // input operates in MMAP no IRQ mode.
+    VOIP_TX      = 0x20, // preferred input for VoIP calls.
+    HW_AV_SYNC   = 0x40, // input connected to an output that uses a hardware A/V sync
+};
+
+@export(name="audio_usage_t", value_prefix="AUDIO_USAGE_")
+enum AudioUsage : int32_t {
+    // These values must kept in sync with
+    //  frameworks/base/media/java/android/media/AudioAttributes.java
+    // Note that not all framework values are exposed
+    UNKNOWN                            = 0,
+    MEDIA                              = 1,
+    VOICE_COMMUNICATION                = 2,
+    VOICE_COMMUNICATION_SIGNALLING     = 3,
+    ALARM                              = 4,
+    NOTIFICATION                       = 5,
+    NOTIFICATION_TELEPHONY_RINGTONE    = 6,
+    ASSISTANCE_ACCESSIBILITY           = 11,
+    ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
+    ASSISTANCE_SONIFICATION            = 13,
+    GAME                               = 14,
+    VIRTUAL_SOURCE                     = 15,
+    ASSISTANT                          = 16,
+};
+
+/** Type of audio generated by an application. */
+@export(name="audio_content_type_t", value_prefix="AUDIO_CONTENT_TYPE_")
+enum AudioContentType : uint32_t {
+    UNKNOWN      = 0,
+    SPEECH       = 1,
+    MUSIC        = 2,
+    MOVIE        = 3,
+    SONIFICATION = 4,
+};
+
+/**
+ * Additional information about the stream passed to hardware decoders.
+ */
+struct AudioOffloadInfo {
+    uint32_t sampleRateHz;
+    bitfield<AudioChannelMask> channelMask;
+    AudioFormat format;
+    AudioStreamType streamType;
+    uint32_t bitRatePerSecond;
+    int64_t durationMicroseconds;  // -1 if unknown
+    bool hasVideo;
+    bool isStreaming;
+    uint32_t bitWidth;
+    uint32_t bufferSize;
+    AudioUsage usage;
+};
+
+/**
+ * Commonly used audio stream configuration parameters.
+ */
+struct AudioConfig {
+    uint32_t sampleRateHz;
+    bitfield<AudioChannelMask> channelMask;
+    AudioFormat format;
+    AudioOffloadInfo offloadInfo;
+    uint64_t frameCount;
+};
+
+
+/*
+ *
+ *  Volume control
+ *
+ */
+
+/**
+ * Type of gain control exposed by an audio port.
+ */
+@export(name="", value_prefix="AUDIO_GAIN_MODE_")
+enum AudioGainMode : uint32_t {
+    JOINT = 0x1,    // supports joint channel gain control
+    CHANNELS = 0x2, // supports separate channel gain control
+    RAMP = 0x4      // supports gain ramps
+};
+
+/**
+ * An audio_gain struct is a representation of a gain stage.
+ * A gain stage is always attached to an audio port.
+ */
+struct AudioGain {
+    bitfield<AudioGainMode> mode;
+    bitfield<AudioChannelMask> channelMask; // channels which gain an be controlled
+    int32_t minValue;     // minimum gain value in millibels
+    int32_t maxValue;     // maximum gain value in millibels
+    int32_t defaultValue; // default gain value in millibels
+    uint32_t stepValue;   // gain step in millibels
+    uint32_t minRampMs;   // minimum ramp duration in ms
+    uint32_t maxRampMs;   // maximum ramp duration in ms
+};
+
+/**
+ * The gain configuration structure is used to get or set the gain values of a
+ * given port.
+ */
+struct AudioGainConfig {
+    int32_t index;  // index of the corresponding AudioGain in AudioPort.gains
+    AudioGainMode mode;
+    AudioChannelMask channelMask;  // channels which gain value follows
+    /**
+     * 4 = sizeof(AudioChannelMask),
+     * 8 is not "FCC_8", so it won't need to be changed for > 8 channels.
+     * Gain values in millibels for each channel ordered from LSb to MSb in
+     * channel mask. The number of values is 1 in joint mode or
+     * popcount(channel_mask).
+     */
+    int32_t[4 * 8] values;
+    uint32_t rampDurationMs;  // ramp duration in ms
+};
+
+
+/*
+ *
+ *  Routing control
+ *
+ */
+
+/*
+ * Types defined here are used to describe an audio source or sink at internal
+ * framework interfaces (audio policy, patch panel) or at the audio HAL.
+ * Sink and sources are grouped in a concept of “audio port” representing an
+ * audio end point at the edge of the system managed by the module exposing
+ * the interface.
+ */
+
+/** Audio port role: either source or sink */
+@export(name="audio_port_role_t", value_prefix="AUDIO_PORT_ROLE_")
+enum AudioPortRole : int32_t {
+    NONE,
+    SOURCE,
+    SINK,
+};
+
+/**
+ * Audio port type indicates if it is a session (e.g AudioTrack), a mix (e.g
+ * PlaybackThread output) or a physical device (e.g OUT_SPEAKER)
+ */
+@export(name="audio_port_type_t", value_prefix="AUDIO_PORT_TYPE_")
+enum AudioPortType : int32_t {
+    NONE,
+    DEVICE,
+    MIX,
+    SESSION,
+};
+
+/**
+ * Extension for audio port configuration structure when the audio port is a
+ * hardware device.
+ */
+struct AudioPortConfigDeviceExt {
+    AudioModuleHandle hwModule;  // module the device is attached to
+    AudioDevice type;            // device type (e.g OUT_SPEAKER)
+    uint8_t[32] address;         // device address. "" if N/A
+};
+
+/**
+ * Extension for audio port configuration structure when the audio port is an
+ * audio session.
+ */
+struct AudioPortConfigSessionExt {
+    AudioSession session;
+};
+
+/**
+ * Flags indicating which fields are to be considered in AudioPortConfig.
+ */
+@export(name="", value_prefix="AUDIO_PORT_CONFIG_")
+enum AudioPortConfigMask : uint32_t {
+    SAMPLE_RATE = 0x1,
+    CHANNEL_MASK =  0x2,
+    FORMAT = 0x4,
+    GAIN = 0x8,
+};
+
+/**
+ * Audio port configuration structure used to specify a particular configuration
+ * of an audio port.
+ */
+struct AudioPortConfig {
+    AudioPortHandle id;
+    bitfield<AudioPortConfigMask> configMask;
+    uint32_t sampleRateHz;
+    bitfield<AudioChannelMask> channelMask;
+    AudioFormat format;
+    AudioGainConfig gain;
+    AudioPortType type;  // type is used as a discriminator for Ext union
+    AudioPortRole role;  // role is used as a discriminator for UseCase union
+    union Ext {
+        AudioPortConfigDeviceExt device;
+        struct AudioPortConfigMixExt {
+            AudioModuleHandle hwModule; // module the stream is attached to
+            AudioIoHandle ioHandle;     // I/O handle of the input/output stream
+            union UseCase {
+                AudioStreamType stream;
+                AudioSource source;
+            } useCase;
+        } mix;
+        AudioPortConfigSessionExt session;
+    } ext;
+};
+
+/**
+ * Extension for audio port structure when the audio port is a hardware device.
+ */
+struct AudioPortDeviceExt {
+    AudioModuleHandle hwModule;    // module the device is attached to
+    AudioDevice type;
+    /** 32 byte string identifying the port. */
+    uint8_t[32] address;
+};
+
+/**
+ * Latency class of the audio mix.
+ */
+@export(name="audio_mix_latency_class_t", value_prefix="AUDIO_LATENCY_")
+enum AudioMixLatencyClass : int32_t {
+    LOW,
+    NORMAL
+};
+
+struct AudioPortMixExt {
+    AudioModuleHandle hwModule;     // module the stream is attached to
+    AudioIoHandle ioHandle;         // I/O handle of the stream
+    AudioMixLatencyClass latencyClass;
+};
+
+/**
+ * Extension for audio port structure when the audio port is an audio session.
+ */
+struct AudioPortSessionExt {
+    AudioSession session;
+};
+
+struct AudioPort {
+    AudioPortHandle id;
+    AudioPortRole role;
+    string name;
+    vec<uint32_t> sampleRates;
+    vec<bitfield<AudioChannelMask>> channelMasks;
+    vec<AudioFormat> formats;
+    vec<AudioGain> gains;
+    AudioPortConfig activeConfig; // current audio port configuration
+    AudioPortType type;  // type is used as a discriminator
+    union Ext {
+        AudioPortDeviceExt device;
+        AudioPortMixExt mix;
+        AudioPortSessionExt session;
+    } ext;
+};
+
+struct ThreadInfo {
+    int64_t pid;
+    int64_t tid;
+};
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
new file mode 100644
index 0000000..e7676a9
--- /dev/null
+++ b/audio/effect/4.0/Android.bp
@@ -0,0 +1,47 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.audio.effect@4.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IAcousticEchoCancelerEffect.hal",
+        "IAutomaticGainControlEffect.hal",
+        "IBassBoostEffect.hal",
+        "IDownmixEffect.hal",
+        "IEffect.hal",
+        "IEffectBufferProviderCallback.hal",
+        "IEffectsFactory.hal",
+        "IEnvironmentalReverbEffect.hal",
+        "IEqualizerEffect.hal",
+        "ILoudnessEnhancerEffect.hal",
+        "INoiseSuppressionEffect.hal",
+        "IPresetReverbEffect.hal",
+        "IVirtualizerEffect.hal",
+        "IVisualizerEffect.hal",
+    ],
+    interfaces: [
+        "android.hardware.audio.common@4.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "AudioBuffer",
+        "EffectAuxChannelsConfig",
+        "EffectBufferAccess",
+        "EffectBufferConfig",
+        "EffectConfig",
+        "EffectConfigParameters",
+        "EffectDescriptor",
+        "EffectFeature",
+        "EffectFlags",
+        "EffectOffloadParameter",
+        "MessageQueueFlagBits",
+        "Result",
+    ],
+    gen_java: false,
+    gen_java_constants: true,
+}
+
diff --git a/audio/effect/4.0/IAcousticEchoCancelerEffect.hal b/audio/effect/4.0/IAcousticEchoCancelerEffect.hal
new file mode 100644
index 0000000..f495e6f
--- /dev/null
+++ b/audio/effect/4.0/IAcousticEchoCancelerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IAcousticEchoCancelerEffect extends IEffect {
+    /**
+     * Sets echo delay value in milliseconds.
+     */
+    setEchoDelay(uint32_t echoDelayMs) generates (Result retval);
+
+    /**
+     * Gets echo delay value in milliseconds.
+     */
+    getEchoDelay() generates (Result retval, uint32_t echoDelayMs);
+};
diff --git a/audio/effect/4.0/IAutomaticGainControlEffect.hal b/audio/effect/4.0/IAutomaticGainControlEffect.hal
new file mode 100644
index 0000000..d7fa04c
--- /dev/null
+++ b/audio/effect/4.0/IAutomaticGainControlEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IAutomaticGainControlEffect extends IEffect {
+    /**
+     * Sets target level in millibels.
+     */
+    setTargetLevel(int16_t targetLevelMb) generates (Result retval);
+
+    /**
+     * Gets target level.
+     */
+    getTargetLevel() generates (Result retval, int16_t targetLevelMb);
+
+    /**
+     * Sets gain in the compression range in millibels.
+     */
+    setCompGain(int16_t compGainMb) generates (Result retval);
+
+    /**
+     * Gets gain in the compression range.
+     */
+    getCompGain() generates (Result retval, int16_t compGainMb);
+
+    /**
+     * Enables or disables limiter.
+     */
+    setLimiterEnabled(bool enabled) generates (Result retval);
+
+    /**
+     * Returns whether limiter is enabled.
+     */
+    isLimiterEnabled() generates (Result retval, bool enabled);
+
+    struct AllProperties {
+        int16_t targetLevelMb;
+        int16_t compGainMb;
+        bool limiterEnabled;
+    };
+
+    /**
+     * Sets all properties at once.
+     */
+    setAllProperties(AllProperties properties) generates (Result retval);
+
+    /**
+     * Gets all properties at once.
+     */
+    getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IBassBoostEffect.hal b/audio/effect/4.0/IBassBoostEffect.hal
new file mode 100644
index 0000000..bd302f6
--- /dev/null
+++ b/audio/effect/4.0/IBassBoostEffect.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IBassBoostEffect extends IEffect {
+    /**
+     * Returns whether setting bass boost strength is supported.
+     */
+    isStrengthSupported() generates (Result retval, bool strengthSupported);
+
+    enum StrengthRange : uint16_t {
+        MIN = 0,
+        MAX = 1000
+    };
+
+    /**
+     * Sets bass boost strength.
+     *
+     * @param strength strength of the effect. The valid range for strength
+     *                 strength is [0, 1000], where 0 per mille designates the
+     *                 mildest effect and 1000 per mille designates the
+     *                 strongest.
+     * @return retval operation completion status.
+     */
+    setStrength(uint16_t strength) generates (Result retval);
+
+    /**
+     * Gets virtualization strength.
+     */
+    getStrength() generates (Result retval, uint16_t strength);
+};
diff --git a/audio/effect/4.0/IDownmixEffect.hal b/audio/effect/4.0/IDownmixEffect.hal
new file mode 100644
index 0000000..3ce3a79
--- /dev/null
+++ b/audio/effect/4.0/IDownmixEffect.hal
@@ -0,0 +1,37 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IDownmixEffect extends IEffect {
+    enum Type : int32_t {
+        STRIP, // throw away the extra channels
+        FOLD   // mix the extra channels with FL/FR
+    };
+
+    /**
+     * Sets the current downmix preset.
+     */
+    setType(Type preset) generates (Result retval);
+
+    /**
+     * Gets the current downmix preset.
+     */
+    getType() generates (Result retval, Type preset);
+};
diff --git a/audio/effect/4.0/IEffect.hal b/audio/effect/4.0/IEffect.hal
new file mode 100644
index 0000000..d1d9496
--- /dev/null
+++ b/audio/effect/4.0/IEffect.hal
@@ -0,0 +1,418 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffectBufferProviderCallback;
+
+interface IEffect {
+    /**
+     * Initialize effect engine--all configurations return to default.
+     *
+     * @return retval operation completion status.
+     */
+    @entry
+    init() generates (Result retval);
+
+    /**
+     * Apply new audio parameters configurations for input and output buffers.
+     * The provider callbacks may be empty, but in this case the buffer
+     * must be provided in the EffectConfig structure.
+     *
+     * @param config configuration descriptor.
+     * @param inputBufferProvider optional buffer provider reference.
+     * @param outputBufferProvider optional buffer provider reference.
+     * @return retval operation completion status.
+     */
+    setConfig(EffectConfig config,
+            IEffectBufferProviderCallback inputBufferProvider,
+            IEffectBufferProviderCallback outputBufferProvider)
+            generates (Result retval);
+
+    /**
+     * Reset the effect engine. Keep configuration but resets state and buffer
+     * content.
+     *
+     * @return retval operation completion status.
+     */
+    reset() generates (Result retval);
+
+    /**
+     * Enable processing.
+     *
+     * @return retval operation completion status.
+     */
+    @callflow(next={"prepareForProcessing"})
+    enable() generates (Result retval);
+
+    /**
+     * Disable processing.
+     *
+     * @return retval operation completion status.
+     */
+    @callflow(next={"close"})
+    disable() generates (Result retval);
+
+    /**
+     * Set the rendering device the audio output path is connected to.  The
+     * effect implementation must set EFFECT_FLAG_DEVICE_IND flag in its
+     * descriptor to receive this command when the device changes.
+     *
+     * Note: this method is only supported for effects inserted into
+     *       the output chain.
+     *
+     * @param device output device specification.
+     * @return retval operation completion status.
+     */
+    setDevice(bitfield<AudioDevice> device) generates (Result retval);
+
+    /**
+     * Set and get volume. Used by audio framework to delegate volume control to
+     * effect engine. The effect implementation must set EFFECT_FLAG_VOLUME_CTRL
+     * flag in its descriptor to receive this command. The effect engine must
+     * return the volume that should be applied before the effect is
+     * processed. The overall volume (the volume actually applied by the effect
+     * engine multiplied by the returned value) should match the value indicated
+     * in the command.
+     *
+     * @param volumes vector containing volume for each channel defined in
+     *                EffectConfig for output buffer expressed in 8.24 fixed
+     *                point format.
+     * @return result updated volume values.
+     * @return retval operation completion status.
+     */
+    setAndGetVolume(vec<uint32_t> volumes)
+            generates (Result retval, vec<uint32_t> result);
+
+    /**
+     * Notify the effect of the volume change. The effect implementation must
+     * set EFFECT_FLAG_VOLUME_IND flag in its descriptor to receive this
+     * command.
+     *
+     * @param volumes vector containing volume for each channel defined in
+     *                EffectConfig for output buffer expressed in 8.24 fixed
+     *                point format.
+     * @return retval operation completion status.
+     */
+    volumeChangeNotification(vec<uint32_t> volumes)
+            generates (Result retval);
+
+    /**
+     * Set the audio mode. The effect implementation must set
+     * EFFECT_FLAG_AUDIO_MODE_IND flag in its descriptor to receive this command
+     * when the audio mode changes.
+     *
+     * @param mode desired audio mode.
+     * @return retval operation completion status.
+     */
+    setAudioMode(AudioMode mode) generates (Result retval);
+
+    /**
+     * Apply new audio parameters configurations for input and output buffers of
+     * reverse stream.  An example of reverse stream is the echo reference
+     * supplied to an Acoustic Echo Canceler.
+     *
+     * @param config configuration descriptor.
+     * @param inputBufferProvider optional buffer provider reference.
+     * @param outputBufferProvider optional buffer provider reference.
+     * @return retval operation completion status.
+     */
+    setConfigReverse(EffectConfig config,
+            IEffectBufferProviderCallback inputBufferProvider,
+            IEffectBufferProviderCallback outputBufferProvider)
+            generates (Result retval);
+
+    /**
+     * Set the capture device the audio input path is connected to. The effect
+     * implementation must set EFFECT_FLAG_DEVICE_IND flag in its descriptor to
+     * receive this command when the device changes.
+     *
+     * Note: this method is only supported for effects inserted into
+     *       the input chain.
+     *
+     * @param device input device specification.
+     * @return retval operation completion status.
+     */
+    setInputDevice(bitfield<AudioDevice> device) generates (Result retval);
+
+    /**
+     * Read audio parameters configurations for input and output buffers.
+     *
+     * @return retval operation completion status.
+     * @return config configuration descriptor.
+     */
+    getConfig() generates (Result retval, EffectConfig config);
+
+    /**
+     * Read audio parameters configurations for input and output buffers of
+     * reverse stream.
+     *
+     * @return retval operation completion status.
+     * @return config configuration descriptor.
+     */
+    getConfigReverse() generates (Result retval, EffectConfig config);
+
+    /**
+     * Queries for supported combinations of main and auxiliary channels
+     * (e.g. for a multi-microphone noise suppressor).
+     *
+     * @param maxConfigs maximum number of the combinations to return.
+     * @return retval absence of the feature support is indicated using
+     *                NOT_SUPPORTED code. RESULT_TOO_BIG is returned if
+     *                the number of supported combinations exceeds 'maxConfigs'.
+     * @return result list of configuration descriptors.
+     */
+    getSupportedAuxChannelsConfigs(uint32_t maxConfigs)
+            generates (Result retval, vec<EffectAuxChannelsConfig> result);
+
+    /**
+     * Retrieves the current configuration of main and auxiliary channels.
+     *
+     * @return retval absence of the feature support is indicated using
+     *                NOT_SUPPORTED code.
+     * @return result configuration descriptor.
+     */
+    getAuxChannelsConfig()
+            generates (Result retval, EffectAuxChannelsConfig result);
+
+    /**
+     * Sets the current configuration of main and auxiliary channels.
+     *
+     * @return retval operation completion status; absence of the feature
+     *                support is indicated using NOT_SUPPORTED code.
+     */
+    setAuxChannelsConfig(EffectAuxChannelsConfig config)
+            generates (Result retval);
+
+    /**
+     * Set the audio source the capture path is configured for (Camcorder, voice
+     * recognition...).
+     *
+     * Note: this method is only supported for effects inserted into
+     *       the input chain.
+     *
+     * @param source source descriptor.
+     * @return retval operation completion status.
+     */
+    setAudioSource(AudioSource source) generates (Result retval);
+
+    /**
+     * This command indicates if the playback thread the effect is attached to
+     * is offloaded or not, and updates the I/O handle of the playback thread
+     * the effect is attached to.
+     *
+     * @param param effect offload descriptor.
+     * @return retval operation completion status.
+     */
+    offload(EffectOffloadParameter param) generates (Result retval);
+
+    /**
+     * Returns the effect descriptor.
+     *
+     * @return retval operation completion status.
+     * @return descriptor effect descriptor.
+     */
+    getDescriptor() generates (Result retval, EffectDescriptor descriptor);
+
+    /**
+     * Set up required transports for passing audio buffers to the effect.
+     *
+     * The transport consists of shared memory and a message queue for reporting
+     * effect processing operation status. The shared memory is set up
+     * separately using 'setProcessBuffers' method.
+     *
+     * Processing is requested by setting 'REQUEST_PROCESS' or
+     * 'REQUEST_PROCESS_REVERSE' EventFlags associated with the status message
+     * queue. The result of processing may be one of the following:
+     *   OK if there were no errors during processing;
+     *   INVALID_ARGUMENTS if audio buffers are invalid;
+     *   INVALID_STATE if the engine has finished the disable phase;
+     *   NOT_INITIALIZED if the audio buffers were not set;
+     *   NOT_SUPPORTED if the requested processing type is not supported by
+     *                 the effect.
+     *
+     * @return retval OK if both message queues were created successfully.
+     *                INVALID_STATE if the method was already called.
+     *                INVALID_ARGUMENTS if there was a problem setting up
+     *                                  the queue.
+     * @return statusMQ a message queue used for passing status from the effect.
+     */
+    @callflow(next={"setProcessBuffers"})
+    prepareForProcessing() generates (Result retval, fmq_sync<Result> statusMQ);
+
+    /**
+     * Set up input and output buffers for processing audio data. The effect
+     * may modify both the input and the output buffer during the operation.
+     * Buffers may be set multiple times during effect lifetime.
+     *
+     * The input and the output buffer may be reused between different effects,
+     * and the input buffer may be used as an output buffer. Buffers are
+     * distinguished using 'AudioBuffer.id' field.
+     *
+     * @param inBuffer input audio buffer.
+     * @param outBuffer output audio buffer.
+     * @return retval OK if both buffers were mapped successfully.
+     *                INVALID_ARGUMENTS if there was a problem with mapping
+     *                                  any of the buffers.
+     */
+    setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer)
+            generates (Result retval);
+
+    /**
+     * Execute a vendor specific command on the effect. The command code
+     * and data, as well as result data are not interpreted by Android
+     * Framework and are passed as-is between the application and the effect.
+     *
+     * The effect must use standard POSIX.1-2001 error codes for the operation
+     * completion status.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it. This method only works for effects
+     * implemented in software.
+     *
+     * @param commandId the ID of the command.
+     * @param data command data.
+     * @param resultMaxSize maximum size in bytes of the result; can be 0.
+     * @return status command completion status.
+     * @return result result data.
+     */
+    command(uint32_t commandId, vec<uint8_t> data, uint32_t resultMaxSize)
+            generates (int32_t status, vec<uint8_t> result);
+
+    /**
+     * Set a vendor-specific parameter and apply it immediately. The parameter
+     * code and data are not interpreted by Android Framework and are passed
+     * as-is between the application and the effect.
+     *
+     * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+     * unknown or if provided parameter data is invalid. If the effect does not
+     * support setting vendor-specific parameters, it must return NOT_SUPPORTED.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it. This method only works for effects
+     * implemented in software.
+     *
+     * @param parameter identifying data of the parameter.
+     * @param value the value of the parameter.
+     * @return retval operation completion status.
+     */
+    setParameter(vec<uint8_t> parameter, vec<uint8_t> value)
+            generates (Result retval);
+
+    /**
+     * Get a vendor-specific parameter value. The parameter code and returned
+     * data are not interpreted by Android Framework and are passed as-is
+     * between the application and the effect.
+     *
+     * The effect must use INVALID_ARGUMENTS return code if the parameter ID is
+     * unknown. If the effect does not support setting vendor-specific
+     * parameters, it must return NOT_SUPPORTED.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it.  This method only works for effects
+     * implemented in software.
+     *
+     * @param parameter identifying data of the parameter.
+     * @param valueMaxSize maximum size in bytes of the value.
+     * @return retval operation completion status.
+     * @return result the value of the parameter.
+     */
+    getParameter(vec<uint8_t> parameter, uint32_t valueMaxSize)
+            generates (Result retval, vec<uint8_t> value);
+
+    /**
+     * Get supported configs for a vendor-specific feature. The configs returned
+     * are not interpreted by Android Framework and are passed as-is between the
+     * application and the effect.
+     *
+     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+     * unknown. If the effect does not support getting vendor-specific feature
+     * configs, it must return NOT_SUPPORTED. If the feature is supported but
+     * the total number of supported configurations exceeds the maximum number
+     * indicated by the caller, the method must return RESULT_TOO_BIG.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it.  This method only works for effects
+     * implemented in software.
+     *
+     * @param featureId feature identifier.
+     * @param maxConfigs maximum number of configs to return.
+     * @param configSize size of each config in bytes.
+     * @return retval operation completion status.
+     * @return configsCount number of configs returned.
+     * @return configsData data for all the configs returned.
+     */
+    getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize) generates (
+                    Result retval,
+                    uint32_t configsCount,
+                    vec<uint8_t> configsData);
+
+    /**
+     * Get the current config for a vendor-specific feature. The config returned
+     * is not interpreted by Android Framework and is passed as-is between the
+     * application and the effect.
+     *
+     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+     * unknown. If the effect does not support getting vendor-specific
+     * feature configs, it must return NOT_SUPPORTED.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it.  This method only works for effects
+     * implemented in software.
+     *
+     * @param featureId feature identifier.
+     * @param configSize size of the config in bytes.
+     * @return retval operation completion status.
+     * @return configData config data.
+     */
+    getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize)
+            generates (Result retval, vec<uint8_t> configData);
+
+    /**
+     * Set the current config for a vendor-specific feature. The config data
+     * is not interpreted by Android Framework and is passed as-is between the
+     * application and the effect.
+     *
+     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
+     * unknown. If the effect does not support getting vendor-specific
+     * feature configs, it must return NOT_SUPPORTED.
+     *
+     * Use this method only if the effect is provided by a third party, and
+     * there is no interface defined for it.  This method only works for effects
+     * implemented in software.
+     *
+     * @param featureId feature identifier.
+     * @param configData config data.
+     * @return retval operation completion status.
+     */
+    setCurrentConfigForFeature(uint32_t featureId, vec<uint8_t> configData)
+            generates (Result retval);
+
+    /**
+     * Called by the framework to deinitialize the effect and free up
+     * all the currently allocated resources. It is recommended to close
+     * the effect on the client side as soon as it is becomes unused.
+     *
+     * @return retval OK in case the success.
+     *                INVALID_STATE if the effect was already closed.
+     */
+    @exit
+    close() generates (Result retval);
+};
diff --git a/audio/effect/4.0/IEffectBufferProviderCallback.hal b/audio/effect/4.0/IEffectBufferProviderCallback.hal
new file mode 100644
index 0000000..439383b
--- /dev/null
+++ b/audio/effect/4.0/IEffectBufferProviderCallback.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.audio.effect@4.0;
+
+/**
+ * This callback interface contains functions that can be used by the effect
+ * engine 'process' function to exchange input and output audio buffers.
+ */
+interface IEffectBufferProviderCallback {
+    /**
+     * Called to retrieve a buffer where data should read from by 'process'
+     * function.
+     *
+     * @return buffer audio buffer for processing
+     */
+    getBuffer() generates (AudioBuffer buffer);
+
+    /**
+     * Called to provide a buffer with the data written by 'process' function.
+     *
+     * @param buffer audio buffer for processing
+     */
+    putBuffer(AudioBuffer buffer);
+};
diff --git a/audio/effect/4.0/IEffectsFactory.hal b/audio/effect/4.0/IEffectsFactory.hal
new file mode 100644
index 0000000..034af58
--- /dev/null
+++ b/audio/effect/4.0/IEffectsFactory.hal
@@ -0,0 +1,58 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEffectsFactory {
+    /**
+     * Returns descriptors of different effects in all loaded libraries.
+     *
+     * @return retval operation completion status.
+     * @return result list of effect descriptors.
+     */
+    getAllDescriptors() generates(Result retval, vec<EffectDescriptor> result);
+
+    /**
+     * Returns a descriptor of a particular effect.
+     *
+     * @return retval operation completion status.
+     * @return result effect descriptor.
+     */
+    getDescriptor(Uuid uid) generates(Result retval, EffectDescriptor result);
+
+    /**
+     * Creates an effect engine of the specified type.  To release the effect
+     * engine, it is necessary to release references to the returned effect
+     * object.
+     *
+     * @param uid effect uuid.
+     * @param session audio session to which this effect instance will be
+     *                attached.  All effects created with the same session ID
+     *                are connected in series and process the same signal
+     *                stream.
+     * @param ioHandle identifies the output or input stream this effect is
+     *                 directed to in audio HAL.
+     * @return retval operation completion status.
+     * @return result the interface for the created effect.
+     * @return effectId the unique ID of the effect to be used with
+     *                  IStream::addEffect and IStream::removeEffect methods.
+     */
+    createEffect(Uuid uid, AudioSession session, AudioIoHandle ioHandle)
+        generates (Result retval, IEffect result, uint64_t effectId);
+};
diff --git a/audio/effect/4.0/IEnvironmentalReverbEffect.hal b/audio/effect/4.0/IEnvironmentalReverbEffect.hal
new file mode 100644
index 0000000..21264d2
--- /dev/null
+++ b/audio/effect/4.0/IEnvironmentalReverbEffect.hal
@@ -0,0 +1,178 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEnvironmentalReverbEffect extends IEffect {
+    /**
+     * Sets whether the effect should be bypassed.
+     */
+    setBypass(bool bypass) generates (Result retval);
+
+    /**
+     * Gets whether the effect should be bypassed.
+     */
+    getBypass() generates (Result retval, bool bypass);
+
+    enum ParamRange : int16_t {
+        ROOM_LEVEL_MIN = -6000,
+        ROOM_LEVEL_MAX = 0,
+        ROOM_HF_LEVEL_MIN = -4000,
+        ROOM_HF_LEVEL_MAX = 0,
+        DECAY_TIME_MIN = 100,
+        DECAY_TIME_MAX = 20000,
+        DECAY_HF_RATIO_MIN = 100,
+        DECAY_HF_RATIO_MAX = 1000,
+        REFLECTIONS_LEVEL_MIN = -6000,
+        REFLECTIONS_LEVEL_MAX = 0,
+        REFLECTIONS_DELAY_MIN = 0,
+        REFLECTIONS_DELAY_MAX = 65,
+        REVERB_LEVEL_MIN = -6000,
+        REVERB_LEVEL_MAX = 0,
+        REVERB_DELAY_MIN = 0,
+        REVERB_DELAY_MAX = 65,
+        DIFFUSION_MIN = 0,
+        DIFFUSION_MAX = 1000,
+        DENSITY_MIN = 0,
+        DENSITY_MAX = 1000
+    };
+
+    /**
+     * Sets the room level.
+     */
+    setRoomLevel(int16_t roomLevel) generates (Result retval);
+
+    /**
+     * Gets the room level.
+     */
+    getRoomLevel() generates (Result retval, int16_t roomLevel);
+
+    /**
+     * Sets the room high frequencies level.
+     */
+    setRoomHfLevel(int16_t roomHfLevel) generates (Result retval);
+
+    /**
+     * Gets the room high frequencies level.
+     */
+    getRoomHfLevel() generates (Result retval, int16_t roomHfLevel);
+
+    /**
+     * Sets the room decay time.
+     */
+    setDecayTime(uint32_t decayTime) generates (Result retval);
+
+    /**
+     * Gets the room decay time.
+     */
+    getDecayTime() generates (Result retval, uint32_t decayTime);
+
+    /**
+     * Sets the ratio of high frequencies decay.
+     */
+    setDecayHfRatio(int16_t decayHfRatio) generates (Result retval);
+
+    /**
+     * Gets the ratio of high frequencies decay.
+     */
+    getDecayHfRatio() generates (Result retval, int16_t decayHfRatio);
+
+    /**
+     * Sets the level of reflections in the room.
+     */
+    setReflectionsLevel(int16_t reflectionsLevel) generates (Result retval);
+
+    /**
+     * Gets the level of reflections in the room.
+     */
+    getReflectionsLevel() generates (Result retval, int16_t reflectionsLevel);
+
+    /**
+     * Sets the reflections delay in the room.
+     */
+    setReflectionsDelay(uint32_t reflectionsDelay) generates (Result retval);
+
+    /**
+     * Gets the reflections delay in the room.
+     */
+    getReflectionsDelay() generates (Result retval, uint32_t reflectionsDelay);
+
+    /**
+     * Sets the reverb level of the room.
+     */
+    setReverbLevel(int16_t reverbLevel) generates (Result retval);
+
+    /**
+     * Gets the reverb level of the room.
+     */
+    getReverbLevel() generates (Result retval, int16_t reverbLevel);
+
+    /**
+     * Sets the reverb delay of the room.
+     */
+    setReverbDelay(uint32_t reverDelay) generates (Result retval);
+
+    /**
+     * Gets the reverb delay of the room.
+     */
+    getReverbDelay() generates (Result retval, uint32_t reverbDelay);
+
+    /**
+     * Sets room diffusion.
+     */
+    setDiffusion(int16_t diffusion) generates (Result retval);
+
+    /**
+     * Gets room diffusion.
+     */
+    getDiffusion() generates (Result retval, int16_t diffusion);
+
+    /**
+     * Sets room wall density.
+     */
+    setDensity(int16_t density) generates (Result retval);
+
+    /**
+     * Gets room wall density.
+     */
+    getDensity() generates (Result retval, int16_t density);
+
+    struct AllProperties {
+        int16_t  roomLevel;         // in millibels,    range -6000 to 0
+        int16_t  roomHfLevel;       // in millibels,    range -4000 to 0
+        uint32_t decayTime;         // in milliseconds, range 100 to 20000
+        int16_t  decayHfRatio;      // in permilles,    range 100 to 1000
+        int16_t  reflectionsLevel;  // in millibels,    range -6000 to 0
+        uint32_t reflectionsDelay;  // in milliseconds, range 0 to 65
+        int16_t  reverbLevel;       // in millibels,    range -6000 to 0
+        uint32_t reverbDelay;       // in milliseconds, range 0 to 65
+        int16_t  diffusion;         // in permilles,    range 0 to 1000
+        int16_t  density;           // in permilles,    range 0 to 1000
+    };
+
+    /**
+     * Sets all properties at once.
+     */
+    setAllProperties(AllProperties properties) generates (Result retval);
+
+    /**
+     * Gets all properties at once.
+     */
+    getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IEqualizerEffect.hal b/audio/effect/4.0/IEqualizerEffect.hal
new file mode 100644
index 0000000..58f2b73
--- /dev/null
+++ b/audio/effect/4.0/IEqualizerEffect.hal
@@ -0,0 +1,93 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IEqualizerEffect extends IEffect {
+    /**
+     * Gets the number of frequency bands that the equalizer supports.
+     */
+    getNumBands() generates (Result retval, uint16_t numBands);
+
+    /**
+     * Returns the minimum and maximum band levels supported.
+     */
+    getLevelRange()
+            generates (Result retval, int16_t minLevel, int16_t maxLevel);
+
+    /**
+     * Sets the gain for the given equalizer band.
+     */
+    setBandLevel(uint16_t band, int16_t level) generates (Result retval);
+
+    /**
+     * Gets the gain for the given equalizer band.
+     */
+    getBandLevel(uint16_t band) generates (Result retval, int16_t level);
+
+    /**
+     * Gets the center frequency of the given band, in milliHertz.
+     */
+    getBandCenterFrequency(uint16_t band)
+            generates (Result retval, uint32_t centerFreqmHz);
+
+    /**
+     * Gets the frequency range of the given frequency band, in milliHertz.
+     */
+    getBandFrequencyRange(uint16_t band)
+            generates (Result retval, uint32_t minFreqmHz, uint32_t maxFreqmHz);
+
+    /**
+     * Gets the band that has the most effect on the given frequency
+     * in milliHertz.
+     */
+    getBandForFrequency(uint32_t freqmHz)
+            generates (Result retval, uint16_t band);
+
+    /**
+     * Gets the names of all presets the equalizer supports.
+     */
+    getPresetNames() generates (Result retval, vec<string> names);
+
+    /**
+     * Sets the current preset using the index of the preset in the names
+     * vector returned via 'getPresetNames'.
+     */
+    setCurrentPreset(uint16_t preset) generates (Result retval);
+
+    /**
+     * Gets the current preset.
+     */
+    getCurrentPreset() generates (Result retval, uint16_t preset);
+
+    struct AllProperties {
+        uint16_t curPreset;
+        vec<int16_t> bandLevels;
+    };
+
+    /**
+     * Sets all properties at once.
+     */
+    setAllProperties(AllProperties properties) generates (Result retval);
+
+    /**
+     * Gets all properties at once.
+     */
+    getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/ILoudnessEnhancerEffect.hal b/audio/effect/4.0/ILoudnessEnhancerEffect.hal
new file mode 100644
index 0000000..2421834
--- /dev/null
+++ b/audio/effect/4.0/ILoudnessEnhancerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface ILoudnessEnhancerEffect extends IEffect {
+    /**
+     * Sets target gain expressed in millibels.
+     */
+    setTargetGain(int32_t targetGainMb) generates (Result retval);
+
+    /**
+     * Gets target gain expressed in millibels.
+     */
+    getTargetGain() generates (Result retval, int32_t targetGainMb);
+};
diff --git a/audio/effect/4.0/INoiseSuppressionEffect.hal b/audio/effect/4.0/INoiseSuppressionEffect.hal
new file mode 100644
index 0000000..ce593a0
--- /dev/null
+++ b/audio/effect/4.0/INoiseSuppressionEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface INoiseSuppressionEffect extends IEffect {
+    enum Level : int32_t {
+        LOW,
+        MEDIUM,
+        HIGH
+    };
+
+    /**
+     * Sets suppression level.
+     */
+    setSuppressionLevel(Level level) generates (Result retval);
+
+    /**
+     * Gets suppression level.
+     */
+    getSuppressionLevel() generates (Result retval, Level level);
+
+    enum Type : int32_t {
+        SINGLE_CHANNEL,
+        MULTI_CHANNEL
+    };
+
+    /**
+     * Set suppression type.
+     */
+    setSuppressionType(Type type) generates (Result retval);
+
+    /**
+     * Get suppression type.
+     */
+    getSuppressionType() generates (Result retval, Type type);
+
+    struct AllProperties {
+        Level level;
+        Type type;
+    };
+
+    /**
+     * Sets all properties at once.
+     */
+    setAllProperties(AllProperties properties) generates (Result retval);
+
+    /**
+     * Gets all properties at once.
+     */
+    getAllProperties() generates (Result retval, AllProperties properties);
+};
diff --git a/audio/effect/4.0/IPresetReverbEffect.hal b/audio/effect/4.0/IPresetReverbEffect.hal
new file mode 100644
index 0000000..2417235
--- /dev/null
+++ b/audio/effect/4.0/IPresetReverbEffect.hal
@@ -0,0 +1,43 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IPresetReverbEffect extends IEffect {
+    enum Preset : int32_t {
+        NONE,        // no reverb or reflections
+        SMALLROOM,   // a small room less than five meters in length
+        MEDIUMROOM,  // a medium room with a length of ten meters or less
+        LARGEROOM,   // a large-sized room suitable for live performances
+        MEDIUMHALL,  // a medium-sized hall
+        LARGEHALL,   // a large-sized hall suitable for a full orchestra
+        PLATE,       // synthesis of the traditional plate reverb
+        LAST = PLATE
+    };
+
+    /**
+     * Sets the current preset.
+     */
+    setPreset(Preset preset) generates (Result retval);
+
+    /**
+     * Gets the current preset.
+     */
+    getPreset() generates (Result retval, Preset preset);
+};
diff --git a/audio/effect/4.0/IVirtualizerEffect.hal b/audio/effect/4.0/IVirtualizerEffect.hal
new file mode 100644
index 0000000..52038ca
--- /dev/null
+++ b/audio/effect/4.0/IVirtualizerEffect.hal
@@ -0,0 +1,77 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IVirtualizerEffect extends IEffect {
+    /**
+     * Returns whether setting virtualization strength is supported.
+     */
+    isStrengthSupported() generates (bool strengthSupported);
+
+    enum StrengthRange : uint16_t {
+        MIN = 0,
+        MAX = 1000
+    };
+
+    /**
+     * Sets virtualization strength.
+     *
+     * @param strength strength of the effect. The valid range for strength
+     *                 strength is [0, 1000], where 0 per mille designates the
+     *                 mildest effect and 1000 per mille designates the
+     *                 strongest.
+     * @return retval operation completion status.
+     */
+    setStrength(uint16_t strength) generates (Result retval);
+
+    /**
+     * Gets virtualization strength.
+     */
+    getStrength() generates (Result retval, uint16_t strength);
+
+    struct SpeakerAngle {
+        /** Speaker channel mask */
+        bitfield<AudioChannelMask> mask;
+        // all angles are expressed in degrees and
+        // are relative to the listener.
+        int16_t azimuth; // 0 is the direction the listener faces
+                         // 180 is behind the listener
+                         // -90 is to their left
+        int16_t elevation; // 0 is the horizontal plane
+                           // +90 is above the listener, -90 is below
+    };
+    /**
+     * Retrieves virtual speaker angles for the given channel mask on the
+     * specified device.
+     */
+    getVirtualSpeakerAngles(bitfield<AudioChannelMask> mask, AudioDevice device)
+            generates (Result retval, vec<SpeakerAngle> speakerAngles);
+
+    /**
+     * Forces the virtualizer effect for the given output device.
+     */
+    forceVirtualizationMode(AudioDevice device) generates (Result retval);
+
+    /**
+     * Returns audio device reflecting the current virtualization mode,
+     * AUDIO_DEVICE_NONE when not virtualizing.
+     */
+    getVirtualizationMode() generates (Result retval, AudioDevice device);
+};
diff --git a/audio/effect/4.0/IVisualizerEffect.hal b/audio/effect/4.0/IVisualizerEffect.hal
new file mode 100644
index 0000000..2fee980
--- /dev/null
+++ b/audio/effect/4.0/IVisualizerEffect.hal
@@ -0,0 +1,110 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+import IEffect;
+
+interface IVisualizerEffect extends IEffect {
+    enum CaptureSizeRange : int32_t {
+        MAX = 1024,  // maximum capture size in samples
+        MIN = 128    // minimum capture size in samples
+    };
+
+    /**
+     * Sets the number PCM samples in the capture.
+     */
+    setCaptureSize(uint16_t captureSize) generates (Result retval);
+
+    /**
+     * Gets the number PCM samples in the capture.
+     */
+    getCaptureSize() generates (Result retval, uint16_t captureSize);
+
+    enum ScalingMode : int32_t {
+        // Keep in sync with SCALING_MODE_... in
+        // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+        NORMALIZED = 0,
+        AS_PLAYED = 1
+    };
+
+    /**
+     * Specifies the way the captured data is scaled.
+     */
+    setScalingMode(ScalingMode scalingMode) generates (Result retval);
+
+    /**
+     * Retrieves the way the captured data is scaled.
+     */
+    getScalingMode() generates (Result retval, ScalingMode scalingMode);
+
+    /**
+     * Informs the visualizer about the downstream latency.
+     */
+    setLatency(uint32_t latencyMs) generates (Result retval);
+
+    /**
+     * Gets the downstream latency.
+     */
+    getLatency() generates (Result retval, uint32_t latencyMs);
+
+    enum MeasurementMode : int32_t {
+        // Keep in sync with MEASUREMENT_MODE_... in
+        // frameworks/base/media/java/android/media/audiofx/Visualizer.java
+        NONE = 0x0,
+        PEAK_RMS = 0x1
+    };
+
+    /**
+     * Specifies which measurements are to be made.
+     */
+    setMeasurementMode(MeasurementMode measurementMode)
+            generates (Result retval);
+
+    /**
+     * Retrieves which measurements are to be made.
+     */
+    getMeasurementMode() generates (
+            Result retval, MeasurementMode measurementMode);
+
+    /**
+     * Retrieves the latest PCM snapshot captured by the visualizer engine.  The
+     * number of samples to capture is specified by 'setCaptureSize' parameter.
+     *
+     * @return retval operation completion status.
+     * @return samples samples in 8 bit unsigned format (0 = 0x80)
+     */
+    capture() generates (Result retval, vec<uint8_t> samples);
+
+    struct Measurement {
+        MeasurementMode mode;    // discriminator
+        union Values {
+            struct PeakAndRms {
+                int32_t peakMb;  // millibels
+                int32_t rmsMb;   // millibels
+            } peakAndRms;
+        } value;
+    };
+    /**
+     * Retrieves the latest measurements. The measurements to be made
+     * are specified by 'setMeasurementMode' parameter.
+     *
+     * @return retval operation completion status.
+     * @return result measurement.
+     */
+    measure() generates (Result retval, Measurement result);
+};
diff --git a/audio/effect/4.0/types.hal b/audio/effect/4.0/types.hal
new file mode 100644
index 0000000..0f76601
--- /dev/null
+++ b/audio/effect/4.0/types.hal
@@ -0,0 +1,299 @@
+/*
+ * 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.audio.effect@4.0;
+
+import android.hardware.audio.common@4.0;
+
+enum Result : int32_t {
+    OK,
+    NOT_INITIALIZED,
+    INVALID_ARGUMENTS,
+    INVALID_STATE,
+    NOT_SUPPORTED,
+    RESULT_TOO_BIG
+};
+
+/**
+ * Effect engine capabilities/requirements flags.
+ *
+ * Definitions for flags field of effect descriptor.
+ *
+ * +----------------+--------+--------------------------------------------------
+ * | description    | bits   | values
+ * +----------------+--------+--------------------------------------------------
+ * | connection     | 0..2   | 0 insert: after track process
+ * | mode           |        | 1 auxiliary: connect to track auxiliary
+ * |                |        |  output and use send level
+ * |                |        | 2 replace: replaces track process function;
+ * |                |        |   must implement SRC, volume and mono to stereo.
+ * |                |        | 3 pre processing: applied below audio HAL on in
+ * |                |        | 4 post processing: applied below audio HAL on out
+ * |                |        | 5 - 7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | insertion      | 3..5   | 0 none
+ * | preference     |        | 1 first of the chain
+ * |                |        | 2 last of the chain
+ * |                |        | 3 exclusive (only effect in the insert chain)
+ * |                |        | 4..7 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Volume         | 6..8   | 0 none
+ * | management     |        | 1 implements volume control
+ * |                |        | 2 requires volume indication
+ * |                |        | 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Device         | 9..11  | 0 none
+ * | indication     |        | 1 requires device updates
+ * |                |        | 2, 4 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Sample input   | 12..13 | 1 direct: process() function or
+ * | mode           |        |   EFFECT_CMD_SET_CONFIG command must specify
+ * |                |        |   a buffer descriptor
+ * |                |        | 2 provider: process() function uses the
+ * |                |        |   bufferProvider indicated by the
+ * |                |        |   EFFECT_CMD_SET_CONFIG command to request input.
+ * |                |        |   buffers.
+ * |                |        | 3 both: both input modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Sample output  | 14..15 | 1 direct: process() function or
+ * | mode           |        |   EFFECT_CMD_SET_CONFIG command must specify
+ * |                |        |   a buffer descriptor
+ * |                |        | 2 provider: process() function uses the
+ * |                |        |   bufferProvider indicated by the
+ * |                |        |   EFFECT_CMD_SET_CONFIG command to request output
+ * |                |        |   buffers.
+ * |                |        | 3 both: both output modes are supported
+ * +----------------+--------+--------------------------------------------------
+ * | Hardware       | 16..17 | 0 No hardware acceleration
+ * | acceleration   |        | 1 non tunneled hw acceleration: the process()
+ * |                |        |   function reads the samples, send them to HW
+ * |                |        |   accelerated effect processor, reads back
+ * |                |        |   the processed samples and returns them
+ * |                |        |   to the output buffer.
+ * |                |        | 2 tunneled hw acceleration: the process()
+ * |                |        |   function is transparent. The effect interface
+ * |                |        |   is only used to control the effect engine.
+ * |                |        |   This mode is relevant for global effects
+ * |                |        |   actually applied by the audio hardware on
+ * |                |        |   the output stream.
+ * +----------------+--------+--------------------------------------------------
+ * | Audio Mode     | 18..19 | 0 none
+ * | indication     |        | 1 requires audio mode updates
+ * |                |        | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Audio source   | 20..21 | 0 none
+ * | indication     |        | 1 requires audio source updates
+ * |                |        | 2..3 reserved
+ * +----------------+--------+--------------------------------------------------
+ * | Effect offload | 22     | 0 The effect cannot be offloaded to an audio DSP
+ * | supported      |        | 1 The effect can be offloaded to an audio DSP
+ * +----------------+--------+--------------------------------------------------
+ * | Process        | 23     | 0 The effect implements a process function.
+ * | function       |        | 1 The effect does not implement a process
+ * | not            |        |   function: enabling the effect has no impact
+ * | implemented    |        |   on latency or CPU load.
+ * |                |        |   Effect implementations setting this flag do not
+ * |                |        |   have to implement a process function.
+ * +----------------+--------+--------------------------------------------------
+ */
+@export(name="", value_prefix="EFFECT_FLAG_")
+enum EffectFlags : int32_t {
+    // Insert mode
+    TYPE_SHIFT = 0,
+    TYPE_SIZE = 3,
+    TYPE_MASK = ((1 << TYPE_SIZE) -1) << TYPE_SHIFT,
+    TYPE_INSERT = 0 << TYPE_SHIFT,
+    TYPE_AUXILIARY = 1 << TYPE_SHIFT,
+    TYPE_REPLACE = 2 << TYPE_SHIFT,
+    TYPE_PRE_PROC = 3 << TYPE_SHIFT,
+    TYPE_POST_PROC = 4 << TYPE_SHIFT,
+
+    // Insert preference
+    INSERT_SHIFT = TYPE_SHIFT + TYPE_SIZE,
+    INSERT_SIZE = 3,
+    INSERT_MASK = ((1 << INSERT_SIZE) -1) << INSERT_SHIFT,
+    INSERT_ANY = 0 << INSERT_SHIFT,
+    INSERT_FIRST = 1 << INSERT_SHIFT,
+    INSERT_LAST = 2 << INSERT_SHIFT,
+    INSERT_EXCLUSIVE = 3 << INSERT_SHIFT,
+
+    // Volume control
+    VOLUME_SHIFT = INSERT_SHIFT + INSERT_SIZE,
+    VOLUME_SIZE = 3,
+    VOLUME_MASK = ((1 << VOLUME_SIZE) -1) << VOLUME_SHIFT,
+    VOLUME_CTRL = 1 << VOLUME_SHIFT,
+    VOLUME_IND = 2 << VOLUME_SHIFT,
+    VOLUME_NONE = 0 << VOLUME_SHIFT,
+
+    // Device indication
+    DEVICE_SHIFT = VOLUME_SHIFT + VOLUME_SIZE,
+    DEVICE_SIZE = 3,
+    DEVICE_MASK = ((1 << DEVICE_SIZE) -1) << DEVICE_SHIFT,
+    DEVICE_IND = 1 << DEVICE_SHIFT,
+    DEVICE_NONE = 0 << DEVICE_SHIFT,
+
+    // Sample input modes
+    INPUT_SHIFT = DEVICE_SHIFT + DEVICE_SIZE,
+    INPUT_SIZE = 2,
+    INPUT_MASK = ((1 << INPUT_SIZE) -1) << INPUT_SHIFT,
+    INPUT_DIRECT = 1 << INPUT_SHIFT,
+    INPUT_PROVIDER = 2 << INPUT_SHIFT,
+    INPUT_BOTH = 3 << INPUT_SHIFT,
+
+    // Sample output modes
+    OUTPUT_SHIFT = INPUT_SHIFT + INPUT_SIZE,
+    OUTPUT_SIZE = 2,
+    OUTPUT_MASK = ((1 << OUTPUT_SIZE) -1) << OUTPUT_SHIFT,
+    OUTPUT_DIRECT = 1 << OUTPUT_SHIFT,
+    OUTPUT_PROVIDER = 2 << OUTPUT_SHIFT,
+    OUTPUT_BOTH = 3 << OUTPUT_SHIFT,
+
+    // Hardware acceleration mode
+    HW_ACC_SHIFT = OUTPUT_SHIFT + OUTPUT_SIZE,
+    HW_ACC_SIZE = 2,
+    HW_ACC_MASK = ((1 << HW_ACC_SIZE) -1) << HW_ACC_SHIFT,
+    HW_ACC_SIMPLE = 1 << HW_ACC_SHIFT,
+    HW_ACC_TUNNEL = 2 << HW_ACC_SHIFT,
+
+    // Audio mode indication
+    AUDIO_MODE_SHIFT = HW_ACC_SHIFT + HW_ACC_SIZE,
+    AUDIO_MODE_SIZE = 2,
+    AUDIO_MODE_MASK = ((1 << AUDIO_MODE_SIZE) -1) << AUDIO_MODE_SHIFT,
+    AUDIO_MODE_IND = 1 << AUDIO_MODE_SHIFT,
+    AUDIO_MODE_NONE = 0 << AUDIO_MODE_SHIFT,
+
+    // Audio source indication
+    AUDIO_SOURCE_SHIFT = AUDIO_MODE_SHIFT + AUDIO_MODE_SIZE,
+    AUDIO_SOURCE_SIZE = 2,
+    AUDIO_SOURCE_MASK = ((1 << AUDIO_SOURCE_SIZE) -1) << AUDIO_SOURCE_SHIFT,
+    AUDIO_SOURCE_IND = 1 << AUDIO_SOURCE_SHIFT,
+    AUDIO_SOURCE_NONE = 0 << AUDIO_SOURCE_SHIFT,
+
+    // Effect offload indication
+    OFFLOAD_SHIFT = AUDIO_SOURCE_SHIFT + AUDIO_SOURCE_SIZE,
+    OFFLOAD_SIZE = 1,
+    OFFLOAD_MASK = ((1 << OFFLOAD_SIZE) -1) << OFFLOAD_SHIFT,
+    OFFLOAD_SUPPORTED = 1 << OFFLOAD_SHIFT,
+
+    // Effect has no process indication
+    NO_PROCESS_SHIFT = OFFLOAD_SHIFT + OFFLOAD_SIZE,
+    NO_PROCESS_SIZE = 1,
+    NO_PROCESS_MASK = ((1 << NO_PROCESS_SIZE) -1) << NO_PROCESS_SHIFT,
+    NO_PROCESS = 1 << NO_PROCESS_SHIFT
+};
+
+/**
+ * The effect descriptor contains necessary information to facilitate the
+ * enumeration of the effect engines present in a library.
+ */
+struct EffectDescriptor {
+    Uuid type;             // UUID of to the OpenSL ES interface implemented
+                           // by this effect
+    Uuid uuid;             // UUID for this particular implementation
+    EffectFlags flags;     // effect engine capabilities/requirements flags
+    uint16_t cpuLoad;      // CPU load indication expressed in 0.1 MIPS units
+                           // as estimated on an ARM9E core (ARMv5TE) with 0 WS
+    uint16_t memoryUsage;  // data memory usage expressed in KB and includes
+                           // only dynamically allocated memory
+    uint8_t[64] name;      // human readable effect name
+    uint8_t[64] implementor;  // human readable effect implementor name
+};
+
+/**
+ * A buffer is a chunk of audio data for processing.  Multi-channel audio is
+ * always interleaved. The channel order is from LSB to MSB with regard to the
+ * channel mask definition in audio.h, audio_channel_mask_t, e.g.:
+ * Stereo: L, R; 5.1: FL, FR, FC, LFE, BL, BR.
+ *
+ * The buffer size is expressed in frame count, a frame being composed of
+ * samples for all channels at a given time. Frame size for unspecified format
+ * (AUDIO_FORMAT_OTHER) is 8 bit by definition.
+ */
+struct AudioBuffer {
+    uint64_t id;
+    uint32_t frameCount;
+    memory data;
+};
+
+@export(name="effect_buffer_access_e", value_prefix="EFFECT_BUFFER_")
+enum EffectBufferAccess : int32_t {
+    ACCESS_WRITE,
+    ACCESS_READ,
+    ACCESS_ACCUMULATE
+};
+
+/**
+ * Determines what fields of EffectBufferConfig need to be considered.
+ */
+@export(name="", value_prefix="EFFECT_CONFIG_")
+enum EffectConfigParameters : int32_t {
+    BUFFER = 0x0001,    // buffer field
+    SMP_RATE = 0x0002,  // samplingRate
+    CHANNELS = 0x0004,  // channels
+    FORMAT = 0x0008,    // format
+    ACC_MODE = 0x0010,  // accessMode
+    // Note that the 2.0 ALL have been moved to an helper function
+};
+
+/**
+ * The buffer config structure specifies the input or output audio format
+ * to be used by the effect engine.
+ */
+struct EffectBufferConfig {
+    AudioBuffer buffer;
+    uint32_t samplingRateHz;
+    bitfield<AudioChannelMask> channels;
+    AudioFormat format;
+    EffectBufferAccess accessMode;
+    bitfield<EffectConfigParameters> mask;
+};
+
+struct EffectConfig {
+    EffectBufferConfig inputCfg;
+    EffectBufferConfig outputCfg;
+};
+
+@export(name="effect_feature_e", value_prefix="EFFECT_FEATURE_")
+enum EffectFeature : int32_t {
+    AUX_CHANNELS, // supports auxiliary channels
+                  // (e.g. dual mic noise suppressor)
+    CNT
+};
+
+struct EffectAuxChannelsConfig {
+    bitfield<AudioChannelMask> mainChannels;  // channel mask for main channels
+    bitfield<AudioChannelMask> auxChannels;   // channel mask for auxiliary channels
+};
+
+struct EffectOffloadParameter {
+    bool isOffload;          // true if the playback thread the effect
+                             // is attached to is offloaded
+    AudioIoHandle ioHandle;  // io handle of the playback thread
+                             // the effect is attached to
+};
+
+/**
+ * The message queue flags used to synchronize reads and writes from
+ * the status message queue used by effects.
+ */
+enum MessageQueueFlagBits : uint32_t {
+    DONE_PROCESSING = 1 << 0,
+    REQUEST_PROCESS = 1 << 1,
+    REQUEST_PROCESS_REVERSE = 1 << 2,
+    REQUEST_QUIT = 1 << 3,
+    REQUEST_PROCESS_ALL =
+        REQUEST_PROCESS | REQUEST_PROCESS_REVERSE | REQUEST_QUIT
+};
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index a967049..9335a6c 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -9,13 +9,11 @@
     srcs: [
         "types.hal",
         "IAudioControl.hal",
-        "IAudioControlCallback.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
-        "AudioResult",
         "ContextNumber",
     ],
     gen_java: true,
diff --git a/automotive/audiocontrol/1.0/IAudioControl.hal b/automotive/audiocontrol/1.0/IAudioControl.hal
index fe9ea8e..c029499 100644
--- a/automotive/audiocontrol/1.0/IAudioControl.hal
+++ b/automotive/audiocontrol/1.0/IAudioControl.hal
@@ -16,8 +16,6 @@
 
 package android.hardware.automotive.audiocontrol@1.0;
 
-import IAudioControlCallback;
-
 
 /**
  * Interacts with the car's audio subsystem to manage audio sources and volumes
@@ -25,15 +23,6 @@
 interface IAudioControl {
 
     /**
-     * Registers the required callback object so that we can be notified when the state
-     * of the car's audio system changes. This call must be made when the interface is
-     * initialized.
-     */
-    setCallback(IAudioControlCallback notificationObject)
-        generates (AudioResult result);
-
-
-    /**
      * Called at startup once per context to get the mapping from ContextNumber to
      * busAddress. This lets the car tell the framework to which physical output stream
      * each context should be routed.
diff --git a/automotive/audiocontrol/1.0/IAudioControlCallback.hal b/automotive/audiocontrol/1.0/IAudioControlCallback.hal
deleted file mode 100644
index f5c227e..0000000
--- a/automotive/audiocontrol/1.0/IAudioControlCallback.hal
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.automotive.audiocontrol@1.0;
-
-
-/**
- * Implemented on client (framework) side to receive asynchronous updates from the car.
- */
-interface IAudioControlCallback {
-
-    /**
-     * When the HAL makes this call, any apps currently playing must be asked to
-     * temporarily suspend playback (via an AudioManager::AUDIOFOCUS_LOSS_TRANSIENT event).
-     *
-     * This is only a suggestion. Apps may be slow to react or even ignore this message
-     * entirely. Enforcement, if necessary, must be done at the AudioHAL level as the
-     * samples are delivered. In most instances, this is the way a car should ask for
-     * quiet if it needs it for some important situation, such as warning alarms or chimes.
-     */
-    oneway suggestPausePlayers();
-
-
-    /**
-     * When the HAL makes this case, any apps currently playing must be asked to stop
-     * playing (via an AudioManager::AUDIOFOCUS_LOSS event). Once stopped, the apps must
-     * not resume their playback.
-     *
-     * It should be noted that not all apps or sound sources honor this request, but this
-     * at least gives an app the chance to do the right thing.
-     * Because it premanently stops media, this call is expected to be used only rarely.
-     * Perhaps in the event of an E-call, where resuming music might be undesirable assuming
-     * the driver is now dealing with whatever the emergency is?
-     */
-    oneway suggestStopPlayers();
-
-
-    /**
-     * Receives calls from the HAL when Android should resume normal operations. If the previous
-     * action was a requestPausePlayers, then things that were paused must be told they may
-     * resume.
-     */
-    oneway resumePlayers();
-};
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
index 614c58b..0e074dd 100644
--- a/automotive/audiocontrol/1.0/default/Android.bp
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -19,7 +19,6 @@
     relative_install_path: "hw",
     srcs: [
         "AudioControl.cpp",
-        "AudioControlCallback.cpp",
         "service.cpp"
     ],
     init_rc: ["android.hardware.automotive.audiocontrol@1.0-service.rc"],
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.cpp b/automotive/audiocontrol/1.0/default/AudioControl.cpp
index 419225d..b40f2ae 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.cpp
+++ b/automotive/audiocontrol/1.0/default/AudioControl.cpp
@@ -36,15 +36,6 @@
 };
 
 
-// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
-Return<AudioResult> AudioControl::setCallback(const sp<IAudioControlCallback>& notificationObject) {
-    // Hang onto the provided callback object for future use
-    callback = notificationObject;
-
-    return AudioResult::OK;
-}
-
-
 Return<int32_t> AudioControl::getBusForContext(uint32_t contextNumber) {
     if (contextNumber > sContextNumberMax) {
         ALOGE("Unexpected context number %d (max expected is %d)", contextNumber, sContextCount);
diff --git a/automotive/audiocontrol/1.0/default/AudioControl.h b/automotive/audiocontrol/1.0/default/AudioControl.h
index 3383875..89e41f9 100644
--- a/automotive/audiocontrol/1.0/default/AudioControl.h
+++ b/automotive/audiocontrol/1.0/default/AudioControl.h
@@ -23,16 +23,12 @@
 struct AudioControl : public IAudioControl {
 public:
     // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControl follow.
-    Return<AudioResult> setCallback(const sp<IAudioControlCallback>& notificationObject) override;
     Return<int32_t> getBusForContext(uint32_t contextNumber) override;
     Return<void> setBalanceTowardRight(float value) override;
     Return<void> setFadeTowardFront(float value) override;
 
     // Implementation details
     AudioControl();
-
-private:
-    sp<IAudioControlCallback> callback;
 };
 
 }  // namespace implementation
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp b/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
deleted file mode 100644
index ea79cad..0000000
--- a/automotive/audiocontrol/1.0/default/AudioControlCallback.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#include "AudioControlCallback.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace audiocontrol {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
-Return<void> AudioControlCallback::suggestPausePlayers() {
-    // TODO implement in framework (this is called by the HAL implementation when needed)
-    return Void();
-}
-
-Return<void> AudioControlCallback::suggestStopPlayers() {
-    // TODO implement in framework (this is called by the HAL implementation when needed)
-    return Void();
-}
-
-Return<void> AudioControlCallback::resumePlayers() {
-    // TODO implement in framework (this is called by the HAL implementation when needed)
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace audiocontrol
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/audiocontrol/1.0/default/AudioControlCallback.h b/automotive/audiocontrol/1.0/default/AudioControlCallback.h
deleted file mode 100644
index 1054548..0000000
--- a/automotive/audiocontrol/1.0/default/AudioControlCallback.h
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
-#define ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
-
-#include <android/hardware/automotive/audiocontrol/1.0/IAudioControlCallback.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace audiocontrol {
-namespace V1_0 {
-namespace implementation {
-
-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;
-using ::android::sp;
-
-// TODO:  Move this into packages/services/Car...
-struct AudioControlCallback : public IAudioControlCallback {
-    // Methods from ::android::hardware::automotive::audiocontrol::V1_0::IAudioControlCallback follow.
-    Return<void> suggestPausePlayers() override;
-    Return<void> suggestStopPlayers() override;
-    Return<void> resumePlayers() override;
-
-    // Methods from ::android::hidl::base::V1_0::IBase follow.
-
-};
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace audiocontrol
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_AUTOMOTIVE_AUDIOCONTROL_V1_0_AUDIOCONTROLCALLBACK_H
diff --git a/automotive/audiocontrol/1.0/types.hal b/automotive/audiocontrol/1.0/types.hal
index 6301d3a..04d8d35 100644
--- a/automotive/audiocontrol/1.0/types.hal
+++ b/automotive/audiocontrol/1.0/types.hal
@@ -33,12 +33,3 @@
     NOTIFICATION,   /* Notifications */
     SYSTEM_SOUND,   /* User interaction sounds (button clicks, etc) */
 };
-
-
-/** Error codes used in AudioControl HAL interface. */
-enum AudioResult : uint32_t {
-    OK = 0,
-    NOT_AVAILABLE,
-    INVALID_ARGUMENT,
-    UNDERLYING_SERVICE_ERROR,
-};
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index a0d20f3..bdc44ef 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -48,7 +48,6 @@
         "VehicleHvacFanDirection",
         "VehicleHwKeyInputAction",
         "VehicleIgnitionState",
-        "VehicleInstrumentClusterType",
         "VehiclePropConfig",
         "VehiclePropValue",
         "VehicleProperty",
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 18e8c40..7938b73 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -358,6 +358,14 @@
 
     {.config =
          {
+             .prop = toInt(VehicleProperty::ENGINE_OIL_LEVEL),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {toInt(VehicleOilLevel::NORMAL)}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::ENGINE_OIL_TEMP),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f673d1a..3001213 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -253,6 +253,19 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Engine oil level
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleOilLevel
+     */
+    ENGINE_OIL_LEVEL = (
+        0x0303
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
      * Temperature of engine oil
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
@@ -433,7 +446,7 @@
      * Parking brake state.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     PARKING_BRAKE_ON = (
         0x0402
@@ -442,6 +455,18 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Auto-apply parking brake.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    PARKING_BRAKE_AUTO_APPLY = (
+        0x0403
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
      * Driving status policy.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -825,12 +850,14 @@
     /**
      * Fan Positions Available
      *
-     * This is a bit mask of fan positions available for the zone.  Each entry in
-     * vehicle_hvac_fan_direction is selected by bit position.  For instance, if
-     * only the FAN_DIRECTION_FACE (0x1) and FAN_DIRECTION_DEFROST (0x4) are available,
-     * then this value shall be set to 0x12.
-     *
-     * 0x12 = (1 << 1) | (1 << 4)
+     * This is a bit mask of fan positions available for the zone.  Each available fan direction is
+     * denoted by a separate entry in the vector.  A fan direction may have multiple bits from
+     * vehicle_hvac_fan_direction set.  For instance, a typical car may have the following setting:
+     *   - [0] = FAN_DIRECTION_FACE (0x1)
+     *   - [1] = FAN_DIRECTION_FLOOR (0x2)
+     *   - [2] = FAN_DIRECTION_FACE | FAN_DIRECTION_FLOOR (0x3)
+     *   - [3] = FAN_DIRECTION_DEFROST (0x4)
+     *   - [4] = FAN_DIRECTION_FLOOR | FAN_DIRECTION_DEFROST (0x6)
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -838,7 +865,7 @@
     HVAC_FAN_DIRECTION_AVAILABLE = (
         0x0511
         | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32
+        | VehiclePropertyType:INT32_VEC
         | VehicleArea:ZONE),
 
     /**
@@ -988,41 +1015,6 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to define instrument cluster information.
-     * For VehicleInstrumentClusterType:EXTERNAL_DISPLAY:
-     *  READ:
-     *   int32Values[0] : The current screen mode index. Screen mode is defined
-     *                    as a configuration in car service and represents
-     *                    which area of screen is renderable.
-     *   int32Values[1] : Android can render to instrument cluster (=1) or
-     *                    not(=0). When this is 0, instrument cluster may be
-     *                    rendering some information in the area allocated for
-     *                    android and android side rendering is invisible.
-     *  WRITE from android:
-     *   int32Values[0] : Preferred mode for android side. Depending on the app
-     *                    rendering to instrument cluster, preferred mode can
-     *                    change. Instrument cluster still needs to send
-     *                    event with new mode to trigger actual mode change.
-     *   int32Values[1] : The current app context relevant for instrument
-     *                    cluster. Use the same flag with
-     *                    VehicleAudioContextFlag but this context represents
-     *                    active apps, not active audio. Instrument cluster
-     *                    side may change mode depending on the currently
-     *                    active contexts.
-     *  When system boots up, Android side will write {0, 0, 0, 0} when it is
-     *  ready to render to instrument cluster. Before this message, rendering
-     *  from android must not be visible in the cluster.
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     * @configArray 0:VehicleInstrumentClusterType 1:hw type
-     */
-    INSTRUMENT_CLUSTER_INFO = (
-        0x0A20
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:INT32_VEC
-        | VehicleArea:GLOBAL),
-
-    /**
      * Current date and time, encoded as Unix time.
      * This value denotes the number of seconds that have elapsed since
      * 1/1/1970.
@@ -1891,9 +1883,18 @@
 enum VehicleHvacFanDirection : int32_t {
     FACE = 0x1,
     FLOOR = 0x2,
-    FACE_AND_FLOOR = 0x3,
     DEFROST = 0x4,
-    DEFROST_AND_FLOOR = 0x5,
+};
+
+enum VehicleOilLevel : int32_t {
+    /**
+     * Oil level values
+     */
+    CRITICALLY_LOW = 0,
+    LOW = 1,
+    NORMAL = 2,
+    HIGH = 3,
+    ERROR = 4,
 };
 
 /**
@@ -2067,25 +2068,6 @@
 };
 
 /**
- * Represents instrument cluster type available in system
- */
-enum VehicleInstrumentClusterType : int32_t {
-  /** Android has no access to instument cluster */
-  NONE = 0,
-
-  /**
-   * Instrument cluster can communicate through vehicle hal with additional
-   * properties to exchange meta-data
-   */
-  HAL_INTERFACE = 1,
-
-  /**
-   * Instrument cluster is external display where android can render contents
-   */
-  EXTERNAL_DISPLAY = 2,
-};
-
-/**
  * Units used for int or float type with no attached enum types.
  */
 enum VehicleUnit : int32_t {
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index a46bcac..e8982e5 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -516,7 +516,7 @@
         if (req.buffers[i].acquireFence >= 0) {
             native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
             handle->data[0] = req.buffers[i].acquireFence;
-            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
         }
     }
 
@@ -554,7 +554,7 @@
             result.outputBuffers[i].status = BufferStatus::ERROR;
             native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
             handle->data[0] = req.buffers[i].acquireFence;
-            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+            result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
             notifyError(req.frameNumber, req.buffers[i].streamId, ErrorCode::ERROR_BUFFER);
         } else {
             result.outputBuffers[i].status = BufferStatus::OK;
@@ -562,7 +562,7 @@
             if (req.buffers[i].acquireFence > 0) {
                 native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
                 handle->data[0] = req.buffers[i].acquireFence;
-                result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/true);
+                result.outputBuffers[i].releaseFence.setTo(handle, /*shouldOwn*/false);
             }
         }
     }
@@ -1543,6 +1543,7 @@
                 halBuf.fenceTimeout = true;
             } else {
                 ::close(halBuf.acquireFence);
+                halBuf.acquireFence = -1;
             }
         }
 
diff --git a/camera/device/3.4/types.hal b/camera/device/3.4/types.hal
index 5ab6b88..c8ebb17 100644
--- a/camera/device/3.4/types.hal
+++ b/camera/device/3.4/types.hal
@@ -31,7 +31,7 @@
  * by the framework by its buffer resolution and format, and additionally by the
  * HAL with the gralloc usage flags and the maximum in-flight buffer count.
  *
- * This version extends the @3.2 Stream with the physicalCameraId field.
+ * This version extends the @3.2 Stream with the physicalCameraId and bufferSize field.
  */
 struct Stream {
     /**
@@ -60,6 +60,21 @@
      * instance names returned by getCameraIdList().
      */
     string physicalCameraId;
+
+    /**
+     * The size of a buffer from this Stream, in bytes.
+     *
+     * For non PixelFormat::BLOB formats, this entry must be 0 and HAL should use
+     * android.hardware.graphics.mapper lockYCbCr API to get buffer layout.
+     *
+     * For BLOB format with dataSpace Dataspace::DEPTH, this must be zero and and HAL must
+     * determine the buffer size based on ANDROID_DEPTH_MAX_DEPTH_SAMPLES.
+     *
+     * For BLOB format with dataSpace Dataspace::JFIF, this must be non-zero and represent the
+     * maximal size HAL can lock using android.hardware.graphics.mapper lock API.
+     *
+     */
+    uint32_t bufferSize;
 };
 
 /**
@@ -170,7 +185,9 @@
  * PhysicalCameraSetting:
  *
  * Individual camera settings for logical camera backed by multiple physical devices.
- * Clients are allowed to pass separate settings for each physical device.
+ * Clients are allowed to pass separate settings for each physical device that has
+ * corresponding configured HalStream and the respective stream id is present in the
+ * output buffers of the capture request.
  */
 struct PhysicalCameraSetting {
     /**
@@ -182,8 +199,9 @@
 
     /**
      * Contains the physical device camera id. Any settings passed by client here
-     * should be applied for this physical device. In case the physical id is invalid
-     * Hal should fail the process request and return Status::ILLEGAL_ARGUMENT.
+     * should be applied for this physical device. In case the physical id is invalid or
+     * it is not present among the last configured streams, Hal should fail the process
+     * request and return Status::ILLEGAL_ARGUMENT.
      */
     string physicalCameraId;
 
@@ -223,7 +241,12 @@
 
     /**
      * A vector containing individual camera settings for logical camera backed by multiple physical
-     * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'.
+     * devices. In case the vector is empty, Hal should use the settings field in 'v3_2'. The
+     * individual settings should only be honored for physical devices that have respective Hal
+     * stream. Physical devices that have a corresponding Hal stream but don't have attached
+     * settings here should use the settings field in 'v3_2'.
+     * If any of the physical settings in the array are applied on one or more devices, then the
+     * visual effect on any Hal streams attached to the logical camera is undefined.
      */
     vec<PhysicalCameraSetting> physicalCameraSettings;
 };
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 4652efd..1405ea9 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -20,6 +20,7 @@
 #include <mutex>
 #include <regex>
 #include <unordered_map>
+#include <unordered_set>
 #include <condition_variable>
 
 #include <inttypes.h>
@@ -28,6 +29,7 @@
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
 #include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
 #include <android/hardware/camera/provider/2.4/ICameraProvider.h>
 #include <android/hidl/manager/1.0/IServiceManager.h>
 #include <binder/MemoryHeapBase.h>
@@ -531,8 +533,10 @@
      }
     };
 
-    struct DeviceCb : public ICameraDeviceCallback {
+    struct DeviceCb : public V3_4::ICameraDeviceCallback {
         DeviceCb(CameraHidlTest *parent) : mParent(parent) {}
+        Return<void> processCaptureResult_3_4(
+                const hidl_vec<V3_4::CaptureResult>& results) override;
         Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
         Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
 
@@ -627,6 +631,15 @@
             ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
             ::android::hardware::camera::device::V3_4::StreamConfiguration *config3_4);
 
+    void configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
+            sp<ICameraProvider> provider,
+            const AvailableStream *previewThreshold,
+            const std::unordered_set<std::string>& physicalIds,
+            sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
+            V3_2::Stream* previewStream /*out*/,
+            device::V3_4::HalStreamConfiguration *halStreamConfig /*out*/,
+            bool *supportsPartialResults /*out*/,
+            uint32_t *partialResultCount /*out*/);
     void configurePreviewStream(const std::string &name, int32_t deviceVersion,
             sp<ICameraProvider> provider,
             const AvailableStream *previewThreshold,
@@ -641,7 +654,7 @@
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
     static Status isLogicalMultiCamera(camera_metadata_t *staticMeta);
     static Status getPhysicalCameraIds(camera_metadata_t *staticMeta,
-            std::vector<std::string> *physicalIds/*out*/);
+            std::unordered_set<std::string> *physicalIds/*out*/);
     static Status pickConstrainedModeSize(camera_metadata_t *staticMeta,
             AvailableStream &hfrStream);
     static Status isZSLModeAvailable(camera_metadata_t *staticMeta);
@@ -844,6 +857,27 @@
     return Void();
 }
 
+Return<void> CameraHidlTest::DeviceCb::processCaptureResult_3_4(
+        const hidl_vec<V3_4::CaptureResult>& results) {
+
+    if (nullptr == mParent) {
+        return Void();
+    }
+
+    bool notify = false;
+    std::unique_lock<std::mutex> l(mParent->mLock);
+    for (size_t i = 0 ; i < results.size(); i++) {
+        notify = processCaptureResultLocked(results[i].v3_2);
+    }
+
+    l.unlock();
+    if (notify) {
+        mParent->mResultCondition.notify_one();
+    }
+
+    return Void();
+}
+
 Return<void> CameraHidlTest::DeviceCb::processCaptureResult(
         const hidl_vec<CaptureResult>& results) {
     if (nullptr == mParent) {
@@ -3304,7 +3338,7 @@
 TEST_F(CameraHidlTest, processMultiCaptureRequestPreview) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
     AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+                                        static_cast<int32_t>(PixelFormat::YCBCR_420_888)};
     uint64_t bufferId = 1;
     uint32_t frameNumber = 1;
     ::android::hardware::hidl_vec<uint8_t> settings;
@@ -3327,7 +3361,7 @@
             ASSERT_TRUE(ret.isOk());
             continue;
         }
-        std::vector<std::string> physicalIds;
+        std::unordered_set<std::string> physicalIds;
         rc = getPhysicalCameraIds(staticMeta, &physicalIds);
         ASSERT_TRUE(Status::OK == rc);
         ASSERT_TRUE(physicalIds.size() > 1);
@@ -3336,22 +3370,23 @@
         ret = session->close();
         ASSERT_TRUE(ret.isOk());
 
-        V3_2::Stream previewStream;
-        HalStreamConfiguration halStreamConfig;
+        // Leave only 2 physical devices in the id set.
+        auto it = physicalIds.begin(); it++; it++;
+        physicalIds.erase(it, physicalIds.end());
+
+        V3_4::HalStreamConfiguration halStreamConfig;
         bool supportsPartialResults = false;
         uint32_t partialResultCount = 0;
-        configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold, &session /*out*/,
-                &previewStream /*out*/, &halStreamConfig /*out*/,
-                &supportsPartialResults /*out*/,
-                &partialResultCount /*out*/);
-        sp<device::V3_3::ICameraDeviceSession> session3_3;
+        V3_2::Stream previewStream;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
-        castSession(session, deviceVersion, &session3_3, &session3_4);
+        configurePreviewStreams3_4(name, deviceVersion, mProvider, &previewThreshold, physicalIds,
+                &session3_4, &previewStream, &halStreamConfig /*out*/,
+                &supportsPartialResults /*out*/, &partialResultCount /*out*/);
         ASSERT_NE(session3_4, nullptr);
 
         std::shared_ptr<ResultMetadataQueue> resultQueue;
         auto resultQueueRet =
-            session->getCaptureResultMetadataQueue(
+            session3_4->getCaptureResultMetadataQueue(
                 [&resultQueue](const auto& descriptor) {
                     resultQueue = std::make_shared<ResultMetadataQueue>(
                             descriptor);
@@ -3365,38 +3400,40 @@
                 });
         ASSERT_TRUE(resultQueueRet.isOk());
 
-        InFlightRequest inflightReq = {1, false, supportsPartialResults,
-                                       partialResultCount, resultQueue};
+        InFlightRequest inflightReq = {static_cast<ssize_t> (physicalIds.size()), false,
+            supportsPartialResults, partialResultCount, resultQueue};
 
         RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
-        ret = session->constructDefaultRequestSettings(reqTemplate,
+        ret = session3_4->constructDefaultRequestSettings(reqTemplate,
                                                        [&](auto status, const auto& req) {
                                                            ASSERT_EQ(Status::OK, status);
                                                            settings = req;
                                                        });
         ASSERT_TRUE(ret.isOk());
+        ASSERT_TRUE(settings.size() > 0);
 
-        sp<GraphicBuffer> gb = new GraphicBuffer(
-            previewStream.width, previewStream.height,
-            static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
-            android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
-                                            halStreamConfig.streams[0].consumerUsage));
-        ASSERT_NE(nullptr, gb.get());
+        std::vector<sp<GraphicBuffer>> graphicBuffers;
+        graphicBuffers.reserve(physicalIds.size());
         ::android::hardware::hidl_vec<StreamBuffer> outputBuffers;
-        outputBuffers.resize(1);
-        outputBuffers[0] = {halStreamConfig.streams[0].id,
-                                     bufferId,
-                                     hidl_handle(gb->getNativeBuffer()->handle),
-                                     BufferStatus::OK,
-                                     nullptr,
-                                     nullptr};
-
-        StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr,
-                                         nullptr};
+        outputBuffers.resize(physicalIds.size());
         hidl_vec<V3_4::PhysicalCameraSetting> camSettings;
-        camSettings.resize(2);
-        camSettings[0] = {0, hidl_string(physicalIds[0]), settings};
-        camSettings[1] = {0, hidl_string(physicalIds[1]), settings};
+        camSettings.resize(physicalIds.size());
+        size_t k = 0;
+        for (const auto physicalIdIt : physicalIds) {
+            sp<GraphicBuffer> gb = new GraphicBuffer(previewStream.width, previewStream.height,
+                    static_cast<int32_t>(halStreamConfig.streams[k].v3_3.v3_2.overrideFormat), 1,
+                    android_convertGralloc1To0Usage(
+                        halStreamConfig.streams[k].v3_3.v3_2.producerUsage,
+                        halStreamConfig.streams[k].v3_3.v3_2.consumerUsage));
+            ASSERT_NE(nullptr, gb.get());
+            outputBuffers[k] = {halStreamConfig.streams[k].v3_3.v3_2.id, bufferId,
+                hidl_handle(gb->getNativeBuffer()->handle), BufferStatus::OK, nullptr, nullptr};
+            graphicBuffers.push_back(gb);
+            camSettings[k] = {0, hidl_string(physicalIdIt), settings};
+            k++;
+        }
+
+        StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
         V3_4::CaptureRequest request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
                                   emptyInputBuffer, outputBuffers}, camSettings};
 
@@ -3421,22 +3458,20 @@
         {
             std::unique_lock<std::mutex> l(mLock);
             while (!inflightReq.errorCodeValid &&
-                   ((0 < inflightReq.numBuffersLeft) ||
-                           (!inflightReq.haveResultMetadata))) {
+                    ((0 < inflightReq.numBuffersLeft) ||
+                     (!inflightReq.haveResultMetadata))) {
                 auto timeout = std::chrono::system_clock::now() +
-                               std::chrono::seconds(kStreamBufferTimeoutSec);
+                    std::chrono::seconds(kStreamBufferTimeoutSec);
                 ASSERT_NE(std::cv_status::timeout,
                         mResultCondition.wait_until(l, timeout));
             }
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(halStreamConfig.streams[0].id,
-                    inflightReq.resultOutputBuffers[0].streamId);
         }
 
         // Empty physical camera settings should fail process requests
-        camSettings[1] = {0, hidl_string(physicalIds[1]), emptySettings};
+        camSettings[1].settings = emptySettings;
         frameNumber++;
         request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
             emptyInputBuffer, outputBuffers}, camSettings};
@@ -3449,7 +3484,8 @@
         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
 
         // Invalid physical camera id should fail process requests
-        camSettings[1] = {0, invalidPhysicalId, settings};
+        camSettings[1].physicalCameraId = invalidPhysicalId;
+        camSettings[1].settings = settings;
         request = {{frameNumber, 0 /* fmqSettingsSize */, settings,
             emptyInputBuffer, outputBuffers}, camSettings};
         returnStatus = session3_4->processCaptureRequest_3_4(
@@ -3460,7 +3496,7 @@
         ASSERT_TRUE(returnStatus.isOk());
         ASSERT_EQ(Status::ILLEGAL_ARGUMENT, stat);
 
-        ret = session->close();
+        ret = session3_4->close();
         ASSERT_TRUE(ret.isOk());
     }
 }
@@ -3838,7 +3874,7 @@
 
 // Generate a list of physical camera ids backing a logical multi-camera.
 Status CameraHidlTest::getPhysicalCameraIds(camera_metadata_t *staticMeta,
-        std::vector<std::string> *physicalIds) {
+        std::unordered_set<std::string> *physicalIds) {
     if ((nullptr == staticMeta) || (nullptr == physicalIds)) {
         return Status::ILLEGAL_ARGUMENT;
     }
@@ -3856,7 +3892,7 @@
         if (ids[i] == '\0') {
             if (start != i) {
                 std::string currentId(reinterpret_cast<const char *> (ids + start));
-                physicalIds->push_back(currentId);
+                physicalIds->emplace(currentId);
             }
             start = i + 1;
         }
@@ -4028,6 +4064,111 @@
     *config3_2 = {streams3_2, configMode};
 }
 
+// Configure multiple preview streams using different physical ids.
+void CameraHidlTest::configurePreviewStreams3_4(const std::string &name, int32_t deviceVersion,
+        sp<ICameraProvider> provider,
+        const AvailableStream *previewThreshold,
+        const std::unordered_set<std::string>& physicalIds,
+        sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
+        V3_2::Stream *previewStream /*out*/,
+        device::V3_4::HalStreamConfiguration *halStreamConfig /*out*/,
+        bool *supportsPartialResults /*out*/,
+        uint32_t *partialResultCount /*out*/) {
+    ASSERT_NE(nullptr, session3_4);
+    ASSERT_NE(nullptr, halStreamConfig);
+    ASSERT_NE(nullptr, previewStream);
+    ASSERT_NE(nullptr, supportsPartialResults);
+    ASSERT_NE(nullptr, partialResultCount);
+    ASSERT_FALSE(physicalIds.empty());
+
+    std::vector<AvailableStream> outputPreviewStreams;
+    ::android::sp<ICameraDevice> device3_x;
+    ALOGI("configureStreams: Testing camera device %s", name.c_str());
+    Return<void> ret;
+    ret = provider->getCameraDeviceInterface_V3_x(
+        name,
+        [&](auto status, const auto& device) {
+            ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
+                  (int)status);
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_NE(device, nullptr);
+            device3_x = device;
+        });
+    ASSERT_TRUE(ret.isOk());
+
+    sp<DeviceCb> cb = new DeviceCb(this);
+    sp<ICameraDeviceSession> session;
+    ret = device3_x->open(
+        cb,
+        [&session](auto status, const auto& newSession) {
+            ALOGI("device::open returns status:%d", (int)status);
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_NE(newSession, nullptr);
+            session = newSession;
+        });
+    ASSERT_TRUE(ret.isOk());
+
+    sp<device::V3_3::ICameraDeviceSession> session3_3;
+    castSession(session, deviceVersion, &session3_3, session3_4);
+    ASSERT_NE(nullptr, session3_4);
+
+    camera_metadata_t *staticMeta;
+    ret = device3_x->getCameraCharacteristics([&] (Status s,
+            CameraMetadata metadata) {
+        ASSERT_EQ(Status::OK, s);
+        staticMeta = clone_camera_metadata(
+                reinterpret_cast<const camera_metadata_t*>(metadata.data()));
+         ASSERT_NE(nullptr, staticMeta);
+    });
+    ASSERT_TRUE(ret.isOk());
+
+    camera_metadata_ro_entry entry;
+    auto status = find_camera_metadata_ro_entry(staticMeta,
+            ANDROID_REQUEST_PARTIAL_RESULT_COUNT, &entry);
+    if ((0 == status) && (entry.count > 0)) {
+        *partialResultCount = entry.data.i32[0];
+        *supportsPartialResults = (*partialResultCount > 1);
+    }
+
+    outputPreviewStreams.clear();
+    auto rc = getAvailableOutputStreams(staticMeta,
+            outputPreviewStreams, previewThreshold);
+    free_camera_metadata(staticMeta);
+    ASSERT_EQ(Status::OK, rc);
+    ASSERT_FALSE(outputPreviewStreams.empty());
+
+    ::android::hardware::hidl_vec<V3_4::Stream> streams3_4(physicalIds.size());
+    int32_t streamId = 0;
+    for (auto const& physicalId : physicalIds) {
+        V3_4::Stream stream3_4 = {{streamId, StreamType::OUTPUT,
+            static_cast<uint32_t> (outputPreviewStreams[0].width),
+            static_cast<uint32_t> (outputPreviewStreams[0].height),
+            static_cast<PixelFormat> (outputPreviewStreams[0].format),
+            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0, StreamRotation::ROTATION_0},
+            physicalId.c_str(), /*bufferSize*/ 0};
+        streams3_4[streamId++] = stream3_4;
+    }
+
+    ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
+    config3_4 = {streams3_4, StreamConfigurationMode::NORMAL_MODE, {}};
+    RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+    ret = (*session3_4)->constructDefaultRequestSettings(reqTemplate,
+            [&config3_4](auto status, const auto& req) {
+            ASSERT_EQ(Status::OK, status);
+            config3_4.sessionParams = req;
+            });
+    ASSERT_TRUE(ret.isOk());
+
+    ret = (*session3_4)->configureStreams_3_4(config3_4,
+            [&] (Status s, device::V3_4::HalStreamConfiguration halConfig) {
+            ASSERT_EQ(Status::OK, s);
+            ASSERT_EQ(physicalIds.size(), halConfig.streams.size());
+            *halStreamConfig = halConfig;
+            });
+    *previewStream = streams3_4[0].v3_2;
+    ASSERT_TRUE(ret.isOk());
+}
+
 // Open a device session and configure a preview stream.
 void CameraHidlTest::configurePreviewStream(const std::string &name, int32_t deviceVersion,
         sp<ICameraProvider> provider,
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c444dde..002ff31 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -256,6 +256,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.secure_element</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISecureElement</name>
+            <instance>eSE1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.sensors</name>
         <version>1.0</version>
         <interface>
diff --git a/drm/1.1/ICryptoFactory.hal b/drm/1.1/ICryptoFactory.hal
index a1a7480..1f8caa5 100644
--- a/drm/1.1/ICryptoFactory.hal
+++ b/drm/1.1/ICryptoFactory.hal
@@ -23,11 +23,11 @@
  * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
  * which are used by a codec to decrypt protected video content.
  *
- * The 1.1 factory must always create 1.1 ICryptoPlugin interfaces, which are
+ * The 1.1 factory must always create 1.0 ICryptoPlugin interfaces, which are
  * returned via the 1.0 createPlugin method.
  *
- * To use 1.1 features the caller must cast the returned interface to a
- * 1.1 HAL, using V1_1::ICryptoPlugin::castFrom().
+ * The ICryptoFactory hal is required because all top-level interfaces
+ * have to be updated in a minor uprev.
  */
 interface ICryptoFactory extends @1.0::ICryptoFactory {
 };
diff --git a/drm/1.1/IDrmPlugin.hal b/drm/1.1/IDrmPlugin.hal
index c32d2b5..7dd397a 100644
--- a/drm/1.1/IDrmPlugin.hal
+++ b/drm/1.1/IDrmPlugin.hal
@@ -23,6 +23,8 @@
 import @1.1::DrmMetricGroup;
 import @1.1::HdcpLevel;
 import @1.1::KeyRequestType;
+import @1.0::SecureStopId;
+import @1.1::SecureStopRelease;
 import @1.1::SecurityLevel;
 
 /**
@@ -176,4 +178,56 @@
      *         plugin.
      */
     getMetrics() generates (Status status, vec<DrmMetricGroup> metric_groups);
+
+    /**
+     * Get the IDs of all secure stops on the device
+     *
+     * @return status the status of the call. The status must be OK or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+     * IDs cannot be returned.
+     * @return secureStopIds a list of the IDs
+     */
+    getSecureStopIds() generates
+        (Status status, vec<SecureStopId> secureStopIds);
+
+    /**
+     * Release secure stops given a release message from the key server
+     *
+     * @param ssRelease the secure stop release message identifying one or more
+     * secure stops to release. ssRelease is opaque, it is passed directly from
+     * a DRM license server through the app and media framework to the vendor
+     * HAL module. The format and content of ssRelease must be defined by the
+     * DRM scheme being implemented according to this HAL. The DRM scheme
+     * can be identified by its UUID which can be queried using
+     * IDrmFactory::isCryptoSchemeSupported.
+     *
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if ssRelease is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+     * cannot be released.
+     */
+    releaseSecureStops(SecureStopRelease ssRelease) generates (Status status);
+
+    /**
+     * Remove a secure stop given its secure stop ID, without requiring
+     * a secure stop release response message from the key server.
+     *
+     * @param secureStopId the ID of the secure stop to release.
+     *
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the secureStopId is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure stop
+     * cannot be released.
+     */
+    removeSecureStop(SecureStopId secureStopId) generates (Status status);
+
+    /**
+     * Remove all secure stops on the device without requiring a secure
+     * stop release response message from the key server.
+     *
+     * @return status the status of the call. The status must be OK or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the secure
+     * stops cannot be removed.
+     */
+    removeAllSecureStops() generates (Status status);
 };
diff --git a/drm/1.1/types.hal b/drm/1.1/types.hal
index 94a6e66..015f1b7 100644
--- a/drm/1.1/types.hal
+++ b/drm/1.1/types.hal
@@ -210,3 +210,10 @@
     HW_SECURE_ALL,
 };
 
+/**
+ * Encapsulates a secure stop release opaque object
+ */
+struct SecureStopRelease {
+    vec<uint8_t> opaqueData;
+};
+
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..782f283
--- /dev/null
+++ b/drm/1.1/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalDrmV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "drm_hal_clearkey_test.cpp"
+    ],
+    static_libs: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.0-helper",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+        "libnativehelper",
+        "libssl",
+        "libcrypto",
+    ],
+}
diff --git a/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
new file mode 100644
index 0000000..62cc8b6
--- /dev/null
+++ b/drm/1.1/vts/functional/drm_hal_clearkey_test.cpp
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "drm_hal_clearkey_test@1.1"
+
+#include <android/hardware/drm/1.1/ICryptoFactory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <android/hardware/drm/1.1/IDrmFactory.h>
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.1/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/types.h>
+#include <android/hardware/drm/1.1/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/manager/1.0/IServiceManager.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidlmemory/mapping.h>
+#include <log/log.h>
+#include <memory>
+#include <openssl/aes.h>
+#include <random>
+
+#include "VtsHalHidlTargetTestBase.h"
+#include "VtsHalHidlTargetTestEnvBase.h"
+
+namespace drm = ::android::hardware::drm;
+using ::android::hardware::drm::V1_0::BufferType;
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::KeyedVector;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::drm::V1_0::SecureStopId;
+using ::android::hardware::drm::V1_0::SessionId;
+using ::android::hardware::drm::V1_0::SharedBuffer;
+using ::android::hardware::drm::V1_0::Status;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::drm::V1_0::SubSample;
+
+using ::android::hardware::drm::V1_1::DrmMetricGroup;
+using ::android::hardware::drm::V1_1::HdcpLevel;
+using ::android::hardware::drm::V1_1::ICryptoFactory;
+using ::android::hardware::drm::V1_1::IDrmFactory;
+using ::android::hardware::drm::V1_1::IDrmPlugin;
+using ::android::hardware::drm::V1_1::SecurityLevel;
+using ::android::hardware::drm::V1_1::SecurityLevel;
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+using std::string;
+using std::unique_ptr;
+using std::random_device;
+using std::map;
+using std::mt19937;
+using std::vector;
+
+/**
+ * These clearkey tests use white box knowledge of the legacy clearkey
+ * plugin to verify that the HIDL HAL services and interfaces are working.
+ * It is not intended to verify any vendor's HAL implementation. If you
+ * are looking for vendor HAL tests, see drm_hal_vendor_test.cpp
+ */
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+// To be used in mpd to specify drm scheme for players
+static const uint8_t kClearKeyUUID[16] = {
+    0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+    0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
+
+// Test environment for drm
+class DrmHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static DrmHidlEnvironment* Instance() {
+        static DrmHidlEnvironment* instance = new DrmHidlEnvironment;
+        return instance;
+    }
+
+    virtual void HidlSetUp() override { ALOGI("SetUp DrmHidlEnvironment"); }
+
+    virtual void HidlTearDown() override { ALOGI("TearDown DrmHidlEnvironment"); }
+
+   private:
+    DrmHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(DrmHidlEnvironment);
+};
+
+
+class DrmHalClearkeyTest : public ::testing::VtsHalHidlTargetTestBase {
+public:
+    virtual void SetUp() override {
+        const ::testing::TestInfo* const test_info =
+                ::testing::UnitTest::GetInstance()->current_test_info();
+
+        ALOGD("DrmHalClearkeyTest: Running test %s.%s", test_info->test_case_name(),
+                test_info->name());
+
+        auto manager = android::hardware::defaultServiceManager();
+        ASSERT_NE(nullptr, manager.get());
+        manager->listByInterface(IDrmFactory::descriptor,
+                [&](const hidl_vec<hidl_string> &registered) {
+                    for (const auto &instance : registered) {
+                        sp<IDrmFactory> drmFactory =
+                                ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>(instance);
+                        drmPlugin = createDrmPlugin(drmFactory);
+                        if (drmPlugin != nullptr) {
+                            break;
+                        }
+                    }
+                }
+            );
+
+        manager->listByInterface(ICryptoFactory::descriptor,
+                [&](const hidl_vec<hidl_string> &registered) {
+                    for (const auto &instance : registered) {
+                        sp<ICryptoFactory> cryptoFactory =
+                                ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>(instance);
+                        cryptoPlugin = createCryptoPlugin(cryptoFactory);
+                        if (cryptoPlugin != nullptr) {
+                            break;
+                        }
+                    }
+                }
+            );
+
+        ASSERT_NE(nullptr, drmPlugin.get()) << "Can't find clearkey drm@1.1 plugin";
+        ASSERT_NE(nullptr, cryptoPlugin.get()) << "Can't find clearkey crypto@1.1 plugin";
+    }
+
+
+    virtual void TearDown() override {}
+
+    SessionId openSession();
+    void closeSession(const SessionId& sessionId);
+    hidl_vec<uint8_t> loadKeys(const SessionId& sessionId, const KeyType& type);
+    sp<IMemory> getDecryptMemory(size_t size, size_t index);
+
+  private:
+    sp<IDrmPlugin> createDrmPlugin(sp<IDrmFactory> drmFactory) {
+        if (drmFactory == nullptr) {
+            return nullptr;
+        }
+        sp<IDrmPlugin> plugin = nullptr;
+        auto res = drmFactory->createPlugin(
+                kClearKeyUUID, "",
+                        [&](Status status, const sp<drm::V1_0::IDrmPlugin>& pluginV1_0) {
+                    EXPECT_EQ(Status::OK, status);
+                    plugin = IDrmPlugin::castFrom(pluginV1_0);
+                });
+
+        if (!res.isOk()) {
+            ALOGE("createDrmPlugin remote call failed");
+        }
+        return plugin;
+    }
+
+    sp<ICryptoPlugin> createCryptoPlugin(sp<ICryptoFactory> cryptoFactory) {
+        if (cryptoFactory == nullptr) {
+            return nullptr;
+        }
+        sp<ICryptoPlugin> plugin = nullptr;
+        hidl_vec<uint8_t> initVec;
+        auto res = cryptoFactory->createPlugin(
+                kClearKeyUUID, initVec,
+                        [&](Status status, const sp<drm::V1_0::ICryptoPlugin>& pluginV1_0) {
+                    EXPECT_EQ(Status::OK, status);
+                    plugin = pluginV1_0;
+                });
+        if (!res.isOk()) {
+            ALOGE("createCryptoPlugin remote call failed");
+        }
+        return plugin;
+    }
+
+protected:
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const std::string& expected, const CT& actual) {
+     return type == DrmMetricGroup::ValueType::STRING_TYPE && expected == actual.stringValue;
+ }
+
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const int64_t expected, const CT& actual) {
+     return type == DrmMetricGroup::ValueType::INT64_TYPE && expected == actual.int64Value;
+ }
+
+ template <typename CT>
+ bool ValueEquals(DrmMetricGroup::ValueType type, const double expected, const CT& actual) {
+     return type == DrmMetricGroup::ValueType::DOUBLE_TYPE && expected == actual.doubleValue;
+ }
+
+ template <typename AT, typename VT>
+ bool ValidateMetricAttributeAndValue(const DrmMetricGroup::Metric& metric,
+                                      const std::string& attributeName, const AT& attributeValue,
+                                      const std::string& componentName, const VT& componentValue) {
+     bool validAttribute = false;
+     bool validComponent = false;
+     for (DrmMetricGroup::Attribute attribute : metric.attributes) {
+         if (attribute.name == attributeName &&
+             ValueEquals(attribute.type, attributeValue, attribute)) {
+             validAttribute = true;
+         }
+     }
+     for (DrmMetricGroup::Value value : metric.values) {
+         if (value.componentName == componentName &&
+             ValueEquals(value.type, componentValue, value)) {
+             validComponent = true;
+         }
+     }
+     return validAttribute && validComponent;
+ }
+
+ template <typename AT, typename VT>
+ bool ValidateMetricAttributeAndValue(const hidl_vec<DrmMetricGroup>& metricGroups,
+                                      const std::string& metricName,
+                                      const std::string& attributeName, const AT& attributeValue,
+                                      const std::string& componentName, const VT& componentValue) {
+     bool foundMetric = false;
+     for (const auto& group : metricGroups) {
+         for (const auto& metric : group.metrics) {
+             if (metric.name == metricName) {
+                 foundMetric = foundMetric || ValidateMetricAttributeAndValue(
+                                                  metric, attributeName, attributeValue,
+                                                  componentName, componentValue);
+             }
+         }
+     }
+     return foundMetric;
+ }
+
+ sp<IDrmPlugin> drmPlugin;
+ sp<ICryptoPlugin> cryptoPlugin;
+};
+
+
+/**
+ * Helper method to open a session and verify that a non-empty
+ * session ID is returned
+ */
+SessionId DrmHalClearkeyTest::openSession() {
+    SessionId sessionId;
+
+    auto res = drmPlugin->openSession(
+            [&sessionId](Status status, const SessionId& id) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_NE(0u, id.size());
+                sessionId = id;
+            });
+    EXPECT_OK(res);
+    return sessionId;
+}
+
+/**
+ * Helper method to close a session
+ */
+void DrmHalClearkeyTest::closeSession(const SessionId& sessionId) {
+    EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
+}
+
+/**
+ * Test that the plugin returns valid connected and max HDCP levels
+ */
+TEST_F(DrmHalClearkeyTest, GetHdcpLevels) {
+    auto res = drmPlugin->getHdcpLevels(
+            [&](Status status, const HdcpLevel &connectedLevel,
+                const HdcpLevel &maxLevel) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_GE(connectedLevel, HdcpLevel::HDCP_NONE);
+                EXPECT_LE(maxLevel, HdcpLevel::HDCP_NO_OUTPUT);
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test that the plugin returns valid open and max session counts
+ */
+TEST_F(DrmHalClearkeyTest, GetSessionCounts) {
+    auto res = drmPlugin->getNumberOfSessions(
+            [&](Status status, uint32_t currentSessions,
+                    uint32_t maxSessions) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_GT(maxSessions, (uint32_t)0);
+                EXPECT_GE(currentSessions, (uint32_t)0);
+                EXPECT_LE(currentSessions, maxSessions);
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test that the plugin returns a valid security level for
+ * a valid session
+ */
+TEST_F(DrmHalClearkeyTest, GetSecurityLevel) {
+    SessionId session = openSession();
+    auto res = drmPlugin->getSecurityLevel(session,
+            [&](Status status, SecurityLevel level) {
+                EXPECT_EQ(Status::OK, status);
+                EXPECT_GE(level, SecurityLevel::SW_SECURE_CRYPTO);
+                EXPECT_LE(level, SecurityLevel::HW_SECURE_ALL);
+            });
+    EXPECT_OK(res);
+    closeSession(session);
+}
+
+/**
+ * Test that the plugin returns the documented error
+ * when requesting the security level for an invalid sessionId
+ */
+TEST_F(DrmHalClearkeyTest, GetSecurityLevelInvalidSessionId) {
+    SessionId session;
+    auto res = drmPlugin->getSecurityLevel(session,
+            [&](Status status, SecurityLevel /*level*/) {
+                EXPECT_EQ(Status::BAD_VALUE, status);
+            });
+    EXPECT_OK(res);
+}
+
+/**
+ * Test that setting all valid security levels on a valid sessionId
+ * is supported
+ */
+TEST_F(DrmHalClearkeyTest, SetSecurityLevel) {
+    SessionId session = openSession();
+    for (uint32_t level = static_cast<uint32_t>(SecurityLevel::SW_SECURE_CRYPTO);
+         level <= static_cast<uint32_t>(SecurityLevel::HW_SECURE_ALL); level++) {
+        EXPECT_EQ(Status::OK, drmPlugin->setSecurityLevel(session, static_cast<SecurityLevel>(level)));
+
+        // check that the level got set
+        auto res = drmPlugin->getSecurityLevel(session,
+                [&](Status status, SecurityLevel readLevel) {
+                    EXPECT_EQ(Status::OK, status);
+                    EXPECT_EQ(level, static_cast<uint32_t>(readLevel));
+                });
+        EXPECT_OK(res);
+    }
+    closeSession(session);
+}
+
+/**
+ * Test that setting an invalid security level on a valid
+ * sessionId is prohibited with the documented error code.
+ */
+TEST_F(DrmHalClearkeyTest, SetInvalidSecurityLevel) {
+    SessionId session = openSession();
+    SecurityLevel level = static_cast<SecurityLevel>(
+            static_cast<uint32_t>(SecurityLevel::HW_SECURE_ALL) + 1);
+    Status status = drmPlugin->setSecurityLevel(session, level);
+    EXPECT_EQ(Status::BAD_VALUE, status);
+    closeSession(session);
+}
+
+/**
+ * Test that attempting to set security level on an invalid
+ * (empty) sessionId is prohibited with the documented error
+ * code.
+ */
+TEST_F(DrmHalClearkeyTest, SetSecurityLevelInvalidSessionId) {
+    SessionId session;
+    SecurityLevel level = SecurityLevel::SW_SECURE_CRYPTO;
+    EXPECT_EQ(Status::BAD_VALUE, drmPlugin->setSecurityLevel(session, level));
+}
+
+/**
+ * Test metrics are set appropriately for open and close operations.
+ */
+TEST_F(DrmHalClearkeyTest, GetMetricsSuccess) {
+    SessionId sessionId = openSession();
+    // The first close should be successful.
+    closeSession(sessionId);
+    // The second close should fail (not opened).
+    EXPECT_EQ(Status::ERROR_DRM_SESSION_NOT_OPENED, drmPlugin->closeSession(sessionId));
+
+    auto res = drmPlugin->getMetrics([this](Status status, hidl_vec<DrmMetricGroup> metricGroups) {
+        EXPECT_EQ(Status::OK, status);
+
+        // Verify the open_session metric.
+        EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "open_session", "status",
+                                                    (int64_t)0, "count", (int64_t)1));
+        // Verify the close_session - success metric.
+        EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
+                                                    (int64_t)0, "count", (int64_t)1));
+        // Verify the close_session - error metric.
+        EXPECT_TRUE(ValidateMetricAttributeAndValue(metricGroups, "close_session", "status",
+                                                    (int64_t)Status::ERROR_DRM_SESSION_NOT_OPENED,
+                                                    "count", (int64_t)1));
+    });
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(DrmHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    DrmHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index b4bad2c..0b27922 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -443,5 +443,9 @@
 
             EXPECT_GE(data.position.ageSeconds, 0);
         }
+
+        EXPECT_GE(data.time.timeEstimate, 1514764800000);  // Jan 01 2018 00:00:00
+        EXPECT_GT(data.time.timeUncertaintyNs, 0);
+        EXPECT_GT(data.time.frequencyUncertaintyNsPerSec, 0);
     }
 }
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index ed2ecbb..9980ae0 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -4,11 +4,8 @@
     vendor: true,
     relative_install_path: "hw",
     srcs: ["passthrough.cpp"],
-    static_libs: [
-        "android.hardware.graphics.allocator@2.0-passthrough",
-    ],
     header_libs: [
-        "android.hardware.graphics.allocator@2.0-hal",
+        "android.hardware.graphics.allocator@2.0-passthrough",
     ],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -20,6 +17,7 @@
         "liblog",
         "libutils",
     ],
+    cflags: ["-DLOG_TAG=\"AllocatorHal\""],
 }
 
 cc_binary {
diff --git a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
index 2f3022e..8ca8200 100644
--- a/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
+++ b/graphics/allocator/2.0/utils/hal/include/allocator-hal/2.0/Allocator.h
@@ -39,11 +39,11 @@
 
 namespace detail {
 
-// AllocatorImpl implements IAllocator on top of AllocatorHal
-template <typename IALLOCATOR, typename ALLOCATOR_HAL>
-class AllocatorImpl : public IALLOCATOR {
+// AllocatorImpl implements V2_*::IAllocator on top of V2_*::hal::AllocatorHal
+template <typename Interface, typename Hal>
+class AllocatorImpl : public Interface {
    public:
-    bool init(std::unique_ptr<ALLOCATOR_HAL> hal) {
+    bool init(std::unique_ptr<Hal> hal) {
         mHal = std::move(hal);
         return true;
     }
@@ -74,7 +74,7 @@
     }
 
    protected:
-    std::unique_ptr<ALLOCATOR_HAL> mHal;
+    std::unique_ptr<Hal> mHal;
 };
 
 }  // namespace detail
diff --git a/graphics/allocator/2.0/utils/passthrough/Android.bp b/graphics/allocator/2.0/utils/passthrough/Android.bp
index b956565..95b92cf 100644
--- a/graphics/allocator/2.0/utils/passthrough/Android.bp
+++ b/graphics/allocator/2.0/utils/passthrough/Android.bp
@@ -1,12 +1,7 @@
-cc_library_static {
+cc_library_headers {
     name: "android.hardware.graphics.allocator@2.0-passthrough",
     defaults: ["hidl_defaults"],
     vendor: true,
-    srcs: [
-        "Gralloc0Hal.cpp",
-        "Gralloc1Hal.cpp",
-        "GrallocLoader.cpp",
-    ],
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
@@ -19,11 +14,11 @@
     ],
     header_libs: [
         "android.hardware.graphics.allocator@2.0-hal",
-        "libgrallocmapperincludes",
+        "android.hardware.graphics.mapper@2.0-passthrough_headers",
     ],
     export_header_lib_headers: [
         "android.hardware.graphics.allocator@2.0-hal",
+        "android.hardware.graphics.mapper@2.0-passthrough_headers",
     ],
     export_include_dirs: ["include"],
-    cflags: ["-DLOG_TAG=\"AllocatorHal\""],
 }
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
deleted file mode 100644
index 8edb7dc..0000000
--- a/graphics/allocator/2.0/utils/passthrough/Gralloc0Hal.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <allocator-passthrough/2.0/Gralloc0Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <hardware/gralloc.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc0Hal::~Gralloc0Hal() {
-    if (mDevice) {
-        gralloc_close(mDevice);
-    }
-}
-
-bool Gralloc0Hal::initWithModule(const hw_module_t* module) {
-    int result = gralloc_open(module, &mDevice);
-    if (result) {
-        ALOGE("failed to open gralloc0 device: %s", strerror(-result));
-        mDevice = nullptr;
-        return false;
-    }
-
-    return true;
-}
-
-std::string Gralloc0Hal::dumpDebugInfo() {
-    char buf[4096] = {};
-    if (mDevice->dump) {
-        mDevice->dump(mDevice, buf, sizeof(buf));
-        buf[sizeof(buf) - 1] = '\0';
-    }
-
-    return buf;
-}
-
-Error Gralloc0Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
-                                   uint32_t* outStride,
-                                   std::vector<const native_handle_t*>* outBuffers) {
-    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        return Error::BAD_DESCRIPTOR;
-    }
-
-    Error error = Error::NONE;
-    uint32_t stride = 0;
-    std::vector<const native_handle_t*> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        const native_handle_t* tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        buffers.push_back(tmpBuffer);
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            error = Error::UNSUPPORTED;
-            break;
-        }
-    }
-
-    if (error != Error::NONE) {
-        freeBuffers(buffers);
-        return error;
-    }
-
-    *outStride = stride;
-    *outBuffers = std::move(buffers);
-
-    return Error::NONE;
-}
-
-void Gralloc0Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
-    for (auto buffer : buffers) {
-        int result = mDevice->free(mDevice, buffer);
-        if (result != 0) {
-            ALOGE("failed to free buffer %p: %d", buffer, result);
-        }
-    }
-}
-
-Error Gralloc0Hal::allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
-                                     const native_handle_t** outBuffer, uint32_t* outStride) {
-    if (info.layerCount > 1 || (info.usage >> 32) != 0) {
-        return Error::BAD_VALUE;
-    }
-
-    const native_handle_t* buffer = nullptr;
-    int stride = 0;
-    int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
-                                info.usage, &buffer, &stride);
-    switch (result) {
-        case 0:
-            *outBuffer = buffer;
-            *outStride = stride;
-            return Error::NONE;
-        case -EINVAL:
-            return Error::BAD_VALUE;
-        default:
-            return Error::NO_RESOURCES;
-    }
-}
-
-}  // namespace passthrough
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp b/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
deleted file mode 100644
index e343ecd..0000000
--- a/graphics/allocator/2.0/utils/passthrough/Gralloc1Hal.cpp
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <allocator-passthrough/2.0/Gralloc1Hal.h>
-
-#include <string.h>
-
-#include <GrallocBufferDescriptor.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using mapper::V2_0::implementation::grallocDecodeBufferDescriptor;
-
-Gralloc1Hal::~Gralloc1Hal() {
-    if (mDevice) {
-        gralloc1_close(mDevice);
-    }
-}
-
-bool Gralloc1Hal::initWithModule(const hw_module_t* module) {
-    int result = gralloc1_open(module, &mDevice);
-    if (result) {
-        ALOGE("failed to open gralloc1 device: %s", strerror(-result));
-        mDevice = nullptr;
-        return false;
-    }
-
-    initCapabilities();
-    if (!initDispatch()) {
-        gralloc1_close(mDevice);
-        mDevice = nullptr;
-        return false;
-    }
-
-    return true;
-}
-
-void Gralloc1Hal::initCapabilities() {
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> capabilities(count);
-    mDevice->getCapabilities(mDevice, &count, capabilities.data());
-    capabilities.resize(count);
-
-    for (auto capability : capabilities) {
-        if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
-            mCapabilities.layeredBuffers = true;
-            break;
-        }
-    }
-}
-
-gralloc1_function_pointer_t Gralloc1Hal::getDispatchFunction(
-    gralloc1_function_descriptor_t desc) const {
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        ALOGE("failed to get gralloc1 function %d", desc);
-        return nullptr;
-    }
-    return pfn;
-}
-
-bool Gralloc1Hal::initDispatch() {
-    if (!initDispatchFunction(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
-        !initDispatchFunction(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
-        return false;
-    }
-
-    if (mCapabilities.layeredBuffers) {
-        if (!initDispatchFunction(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-std::string Gralloc1Hal::dumpDebugInfo() {
-    uint32_t len = 0;
-    mDispatch.dump(mDevice, &len, nullptr);
-
-    std::vector<char> buf(len + 1);
-    mDispatch.dump(mDevice, &len, buf.data());
-    buf.resize(len + 1);
-    buf[len] = '\0';
-
-    return buf.data();
-}
-
-Error Gralloc1Hal::allocateBuffers(const BufferDescriptor& descriptor, uint32_t count,
-                                   uint32_t* outStride,
-                                   std::vector<const native_handle_t*>* outBuffers) {
-    mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
-    if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
-        return Error::BAD_DESCRIPTOR;
-    }
-
-    gralloc1_buffer_descriptor_t desc;
-    Error error = createDescriptor(descriptorInfo, &desc);
-    if (error != Error::NONE) {
-        return error;
-    }
-
-    uint32_t stride = 0;
-    std::vector<const native_handle_t*> buffers;
-    buffers.reserve(count);
-
-    // allocate the buffers
-    for (uint32_t i = 0; i < count; i++) {
-        const native_handle_t* tmpBuffer;
-        uint32_t tmpStride;
-        error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
-        if (error != Error::NONE) {
-            break;
-        }
-
-        buffers.push_back(tmpBuffer);
-
-        if (stride == 0) {
-            stride = tmpStride;
-        } else if (stride != tmpStride) {
-            // non-uniform strides
-            error = Error::UNSUPPORTED;
-            break;
-        }
-    }
-
-    mDispatch.destroyDescriptor(mDevice, desc);
-
-    if (error != Error::NONE) {
-        freeBuffers(buffers);
-        return error;
-    }
-
-    *outStride = stride;
-    *outBuffers = std::move(buffers);
-
-    return Error::NONE;
-}
-
-void Gralloc1Hal::freeBuffers(const std::vector<const native_handle_t*>& buffers) {
-    for (auto buffer : buffers) {
-        int32_t error = mDispatch.release(mDevice, buffer);
-        if (error != GRALLOC1_ERROR_NONE) {
-            ALOGE("failed to free buffer %p: %d", buffer, error);
-        }
-    }
-}
-
-Error Gralloc1Hal::toError(int32_t error) {
-    switch (error) {
-        case GRALLOC1_ERROR_NONE:
-            return Error::NONE;
-        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
-            return Error::BAD_DESCRIPTOR;
-        case GRALLOC1_ERROR_BAD_HANDLE:
-            return Error::BAD_BUFFER;
-        case GRALLOC1_ERROR_BAD_VALUE:
-            return Error::BAD_VALUE;
-        case GRALLOC1_ERROR_NOT_SHARED:
-            return Error::NONE;  // this is fine
-        case GRALLOC1_ERROR_NO_RESOURCES:
-            return Error::NO_RESOURCES;
-        case GRALLOC1_ERROR_UNDEFINED:
-        case GRALLOC1_ERROR_UNSUPPORTED:
-        default:
-            return Error::UNSUPPORTED;
-    }
-}
-
-uint64_t Gralloc1Hal::toProducerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t producerUsage =
-        usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                                       BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_WRITE_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::GPU_DATA_BUFFER is always filtered out
-
-    return producerUsage;
-}
-
-uint64_t Gralloc1Hal::toConsumerUsage(uint64_t usage) {
-    // this is potentially broken as we have no idea which private flags
-    // should be filtered out
-    uint64_t consumerUsage =
-        usage &
-        ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-                               BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
-
-    switch (usage & BufferUsage::CPU_READ_MASK) {
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
-            break;
-        case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
-            consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
-            break;
-        default:
-            break;
-    }
-
-    // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
-
-    if (usage & BufferUsage::GPU_DATA_BUFFER) {
-        consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
-    }
-
-    return consumerUsage;
-}
-
-Error Gralloc1Hal::createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
-                                    gralloc1_buffer_descriptor_t* outDescriptor) {
-    gralloc1_buffer_descriptor_t descriptor;
-
-    int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        if (mCapabilities.layeredBuffers) {
-            error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
-        } else if (info.layerCount > 1) {
-            error = GRALLOC1_ERROR_UNSUPPORTED;
-        }
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
-    }
-    if (error == GRALLOC1_ERROR_NONE) {
-        error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
-    }
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outDescriptor = descriptor;
-    } else {
-        mDispatch.destroyDescriptor(mDevice, descriptor);
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Hal::allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
-                                     const native_handle_t** outBuffer, uint32_t* outStride) {
-    const native_handle_t* buffer = nullptr;
-    int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
-        return toError(error);
-    }
-
-    uint32_t stride = 0;
-    error = mDispatch.getStride(mDevice, buffer, &stride);
-    if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
-        mDispatch.release(mDevice, buffer);
-        return toError(error);
-    }
-
-    *outBuffer = buffer;
-    *outStride = stride;
-
-    return Error::NONE;
-}
-
-}  // namespace passthrough
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp b/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
deleted file mode 100644
index dae7a78..0000000
--- a/graphics/allocator/2.0/utils/passthrough/GrallocLoader.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <allocator-passthrough/2.0/GrallocLoader.h>
-
-#include <allocator-hal/2.0/Allocator.h>
-#include <allocator-hal/2.0/AllocatorHal.h>
-#include <allocator-passthrough/2.0/Gralloc0Hal.h>
-#include <allocator-passthrough/2.0/Gralloc1Hal.h>
-#include <hardware/gralloc.h>
-#include <hardware/hardware.h>
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace allocator {
-namespace V2_0 {
-namespace passthrough {
-
-const hw_module_t* GrallocLoader::loadModule() {
-    const hw_module_t* module;
-    int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (error) {
-        ALOGE("failed to get gralloc module");
-        return nullptr;
-    }
-
-    return module;
-}
-
-int GrallocLoader::getModuleMajorApiVersion(const hw_module_t* module) {
-    return (module->module_api_version >> 8) & 0xff;
-}
-
-std::unique_ptr<hal::AllocatorHal> GrallocLoader::createHal(const hw_module_t* module) {
-    int major = getModuleMajorApiVersion(module);
-    switch (major) {
-        case 1: {
-            auto hal = std::make_unique<Gralloc1Hal>();
-            return hal->initWithModule(module) ? std::move(hal) : nullptr;
-        }
-        case 0: {
-            auto hal = std::make_unique<Gralloc0Hal>();
-            return hal->initWithModule(module) ? std::move(hal) : nullptr;
-        }
-        default:
-            ALOGE("unknown gralloc module major version %d", major);
-            return nullptr;
-    }
-}
-
-IAllocator* GrallocLoader::createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
-    auto allocator = std::make_unique<hal::Allocator>();
-    return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
-}
-
-}  // namespace passthrough
-}  // namespace V2_0
-}  // namespace allocator
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
index 8f433b0..6c179be 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc0Hal.h
@@ -16,10 +16,16 @@
 
 #pragma once
 
-#include <allocator-hal/2.0/AllocatorHal.h>
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
 
-struct alloc_device_t;
-struct hw_module_t;
+#include <cstring>  // for strerror
+
+#include <allocator-hal/2.0/AllocatorHal.h>
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
 
 namespace android {
 namespace hardware {
@@ -28,28 +34,125 @@
 namespace V2_0 {
 namespace passthrough {
 
+namespace detail {
+
 using mapper::V2_0::BufferDescriptor;
 using mapper::V2_0::Error;
+using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
 
-class Gralloc0Hal : public virtual hal::AllocatorHal {
+// Gralloc0HalImpl implements V2_*::hal::AllocatorHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
    public:
-    ~Gralloc0Hal();
-    bool initWithModule(const hw_module_t* module);
+    ~Gralloc0HalImpl() {
+        if (mDevice) {
+            gralloc_close(mDevice);
+        }
+    }
 
-    std::string dumpDebugInfo() override;
+    bool initWithModule(const hw_module_t* module) {
+        int result = gralloc_open(module, &mDevice);
+        if (result) {
+            ALOGE("failed to open gralloc0 device: %s", strerror(-result));
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    std::string dumpDebugInfo() override {
+        char buf[4096] = {};
+        if (mDevice->dump) {
+            mDevice->dump(mDevice, buf, sizeof(buf));
+            buf[sizeof(buf) - 1] = '\0';
+        }
+
+        return buf;
+    }
 
     Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
-                          std::vector<const native_handle_t*>* outBuffers) override;
+                          std::vector<const native_handle_t*>* outBuffers) override {
+        mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+        if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+            return Error::BAD_DESCRIPTOR;
+        }
 
-    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+        Error error = Error::NONE;
+        uint32_t stride = 0;
+        std::vector<const native_handle_t*> buffers;
+        buffers.reserve(count);
+
+        // allocate the buffers
+        for (uint32_t i = 0; i < count; i++) {
+            const native_handle_t* tmpBuffer;
+            uint32_t tmpStride;
+            error = allocateOneBuffer(descriptorInfo, &tmpBuffer, &tmpStride);
+            if (error != Error::NONE) {
+                break;
+            }
+
+            buffers.push_back(tmpBuffer);
+
+            if (stride == 0) {
+                stride = tmpStride;
+            } else if (stride != tmpStride) {
+                // non-uniform strides
+                error = Error::UNSUPPORTED;
+                break;
+            }
+        }
+
+        if (error != Error::NONE) {
+            freeBuffers(buffers);
+            return error;
+        }
+
+        *outStride = stride;
+        *outBuffers = std::move(buffers);
+
+        return Error::NONE;
+    }
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+        for (auto buffer : buffers) {
+            int result = mDevice->free(mDevice, buffer);
+            if (result != 0) {
+                ALOGE("failed to free buffer %p: %d", buffer, result);
+            }
+        }
+    }
 
    protected:
     Error allocateOneBuffer(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
-                            const native_handle_t** outBuffer, uint32_t* outStride);
+                            const native_handle_t** outBuffer, uint32_t* outStride) {
+        if (info.layerCount > 1 || (info.usage >> 32) != 0) {
+            return Error::BAD_VALUE;
+        }
+
+        const native_handle_t* buffer = nullptr;
+        int stride = 0;
+        int result = mDevice->alloc(mDevice, info.width, info.height, static_cast<int>(info.format),
+                                    info.usage, &buffer, &stride);
+        switch (result) {
+            case 0:
+                *outBuffer = buffer;
+                *outStride = stride;
+                return Error::NONE;
+            case -EINVAL:
+                return Error::BAD_VALUE;
+            default:
+                return Error::NO_RESOURCES;
+        }
+    }
 
     alloc_device_t* mDevice = nullptr;
 };
 
+}  // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::AllocatorHal>;
+
 }  // namespace passthrough
 }  // namespace V2_0
 }  // namespace allocator
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
index 3126e91..53b5c14 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/Gralloc1Hal.h
@@ -16,8 +16,16 @@
 
 #pragma once
 
+#ifndef LOG_TAG
+#warning "Gralloc1Hal.h included without LOG_TAG"
+#endif
+
+#include <cstring>  // for strerror
+
 #include <allocator-hal/2.0/AllocatorHal.h>
 #include <hardware/gralloc1.h>
+#include <log/log.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
 
 namespace android {
 namespace hardware {
@@ -26,46 +34,302 @@
 namespace V2_0 {
 namespace passthrough {
 
+namespace detail {
+
+using common::V1_0::BufferUsage;
 using mapper::V2_0::BufferDescriptor;
 using mapper::V2_0::Error;
+using mapper::V2_0::passthrough::grallocDecodeBufferDescriptor;
 
-class Gralloc1Hal : public virtual hal::AllocatorHal {
+// Gralloc1HalImpl implements V2_*::hal::AllocatorHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
    public:
-    ~Gralloc1Hal();
-    bool initWithModule(const hw_module_t* module);
+    ~Gralloc1HalImpl() {
+        if (mDevice) {
+            gralloc1_close(mDevice);
+        }
+    }
 
-    std::string dumpDebugInfo() override;
+    bool initWithModule(const hw_module_t* module) {
+        int result = gralloc1_open(module, &mDevice);
+        if (result) {
+            ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+            mDevice = nullptr;
+            return false;
+        }
+
+        initCapabilities();
+        if (!initDispatch()) {
+            gralloc1_close(mDevice);
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    std::string dumpDebugInfo() override {
+        uint32_t len = 0;
+        mDispatch.dump(mDevice, &len, nullptr);
+
+        std::vector<char> buf(len + 1);
+        mDispatch.dump(mDevice, &len, buf.data());
+        buf.resize(len + 1);
+        buf[len] = '\0';
+
+        return buf.data();
+    }
 
     Error allocateBuffers(const BufferDescriptor& descriptor, uint32_t count, uint32_t* outStride,
-                          std::vector<const native_handle_t*>* outBuffers) override;
+                          std::vector<const native_handle_t*>* outBuffers) override {
+        mapper::V2_0::IMapper::BufferDescriptorInfo descriptorInfo;
+        if (!grallocDecodeBufferDescriptor(descriptor, &descriptorInfo)) {
+            return Error::BAD_DESCRIPTOR;
+        }
 
-    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override;
+        gralloc1_buffer_descriptor_t desc;
+        Error error = createDescriptor(descriptorInfo, &desc);
+        if (error != Error::NONE) {
+            return error;
+        }
+
+        uint32_t stride = 0;
+        std::vector<const native_handle_t*> buffers;
+        buffers.reserve(count);
+
+        // allocate the buffers
+        for (uint32_t i = 0; i < count; i++) {
+            const native_handle_t* tmpBuffer;
+            uint32_t tmpStride;
+            error = allocateOneBuffer(desc, &tmpBuffer, &tmpStride);
+            if (error != Error::NONE) {
+                break;
+            }
+
+            buffers.push_back(tmpBuffer);
+
+            if (stride == 0) {
+                stride = tmpStride;
+            } else if (stride != tmpStride) {
+                // non-uniform strides
+                error = Error::UNSUPPORTED;
+                break;
+            }
+        }
+
+        mDispatch.destroyDescriptor(mDevice, desc);
+
+        if (error != Error::NONE) {
+            freeBuffers(buffers);
+            return error;
+        }
+
+        *outStride = stride;
+        *outBuffers = std::move(buffers);
+
+        return Error::NONE;
+    }
+
+    void freeBuffers(const std::vector<const native_handle_t*>& buffers) override {
+        for (auto buffer : buffers) {
+            int32_t error = mDispatch.release(mDevice, buffer);
+            if (error != GRALLOC1_ERROR_NONE) {
+                ALOGE("failed to free buffer %p: %d", buffer, error);
+            }
+        }
+    }
 
    protected:
+    virtual void initCapabilities() {
+        uint32_t count = 0;
+        mDevice->getCapabilities(mDevice, &count, nullptr);
+
+        std::vector<int32_t> capabilities(count);
+        mDevice->getCapabilities(mDevice, &count, capabilities.data());
+        capabilities.resize(count);
+
+        for (auto capability : capabilities) {
+            if (capability == GRALLOC1_CAPABILITY_LAYERED_BUFFERS) {
+                mCapabilities.layeredBuffers = true;
+                break;
+            }
+        }
+    }
+
     template <typename T>
-    bool initDispatchFunction(gralloc1_function_descriptor_t desc, T* outPfn) {
-        auto pfn = getDispatchFunction(desc);
+    bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
         if (pfn) {
             *outPfn = reinterpret_cast<T>(pfn);
             return true;
         } else {
+            ALOGE("failed to get gralloc1 function %d", desc);
             return false;
         }
     }
-    gralloc1_function_pointer_t getDispatchFunction(gralloc1_function_descriptor_t desc) const;
 
-    virtual void initCapabilities();
-    virtual bool initDispatch();
+    virtual bool initDispatch() {
+        if (!initDispatch(GRALLOC1_FUNCTION_DUMP, &mDispatch.dump) ||
+            !initDispatch(GRALLOC1_FUNCTION_CREATE_DESCRIPTOR, &mDispatch.createDescriptor) ||
+            !initDispatch(GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR, &mDispatch.destroyDescriptor) ||
+            !initDispatch(GRALLOC1_FUNCTION_SET_DIMENSIONS, &mDispatch.setDimensions) ||
+            !initDispatch(GRALLOC1_FUNCTION_SET_FORMAT, &mDispatch.setFormat) ||
+            !initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE, &mDispatch.setConsumerUsage) ||
+            !initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE, &mDispatch.setProducerUsage) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride) ||
+            !initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate) ||
+            !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release)) {
+            return false;
+        }
 
-    static Error toError(int32_t error);
-    static uint64_t toProducerUsage(uint64_t usage);
-    static uint64_t toConsumerUsage(uint64_t usage);
+        if (mCapabilities.layeredBuffers) {
+            if (!initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT, &mDispatch.setLayerCount)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    static Error toError(int32_t error) {
+        switch (error) {
+            case GRALLOC1_ERROR_NONE:
+                return Error::NONE;
+            case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+                return Error::BAD_DESCRIPTOR;
+            case GRALLOC1_ERROR_BAD_HANDLE:
+                return Error::BAD_BUFFER;
+            case GRALLOC1_ERROR_BAD_VALUE:
+                return Error::BAD_VALUE;
+            case GRALLOC1_ERROR_NOT_SHARED:
+                return Error::NONE;  // this is fine
+            case GRALLOC1_ERROR_NO_RESOURCES:
+                return Error::NO_RESOURCES;
+            case GRALLOC1_ERROR_UNDEFINED:
+            case GRALLOC1_ERROR_UNSUPPORTED:
+            default:
+                return Error::UNSUPPORTED;
+        }
+    }
+
+    static uint64_t toProducerUsage(uint64_t usage) {
+        // this is potentially broken as we have no idea which private flags
+        // should be filtered out
+        uint64_t producerUsage = usage & ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK |
+                                                                BufferUsage::CPU_WRITE_MASK |
+                                                                BufferUsage::GPU_DATA_BUFFER);
+
+        switch (usage & BufferUsage::CPU_WRITE_MASK) {
+            case static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY):
+                producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+                break;
+            case static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN):
+                producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN;
+                break;
+            default:
+                break;
+        }
+
+        switch (usage & BufferUsage::CPU_READ_MASK) {
+            case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+                producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+                break;
+            case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+                producerUsage |= GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN;
+                break;
+            default:
+                break;
+        }
+
+        // BufferUsage::GPU_DATA_BUFFER is always filtered out
+
+        return producerUsage;
+    }
+
+    static uint64_t toConsumerUsage(uint64_t usage) {
+        // this is potentially broken as we have no idea which private flags
+        // should be filtered out
+        uint64_t consumerUsage =
+            usage &
+            ~static_cast<uint64_t>(BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
+                                   BufferUsage::SENSOR_DIRECT_DATA | BufferUsage::GPU_DATA_BUFFER);
+
+        switch (usage & BufferUsage::CPU_READ_MASK) {
+            case static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY):
+                consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+                break;
+            case static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN):
+                consumerUsage |= GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN;
+                break;
+            default:
+                break;
+        }
+
+        // BufferUsage::SENSOR_DIRECT_DATA is always filtered out
+
+        if (usage & BufferUsage::GPU_DATA_BUFFER) {
+            consumerUsage |= GRALLOC1_CONSUMER_USAGE_GPU_DATA_BUFFER;
+        }
+
+        return consumerUsage;
+    }
 
     Error createDescriptor(const mapper::V2_0::IMapper::BufferDescriptorInfo& info,
-                           gralloc1_buffer_descriptor_t* outDescriptor);
+                           gralloc1_buffer_descriptor_t* outDescriptor) {
+        gralloc1_buffer_descriptor_t descriptor;
+
+        int32_t error = mDispatch.createDescriptor(mDevice, &descriptor);
+
+        if (error == GRALLOC1_ERROR_NONE) {
+            error = mDispatch.setDimensions(mDevice, descriptor, info.width, info.height);
+        }
+        if (error == GRALLOC1_ERROR_NONE) {
+            error = mDispatch.setFormat(mDevice, descriptor, static_cast<int32_t>(info.format));
+        }
+        if (error == GRALLOC1_ERROR_NONE) {
+            if (mCapabilities.layeredBuffers) {
+                error = mDispatch.setLayerCount(mDevice, descriptor, info.layerCount);
+            } else if (info.layerCount > 1) {
+                error = GRALLOC1_ERROR_UNSUPPORTED;
+            }
+        }
+        if (error == GRALLOC1_ERROR_NONE) {
+            error = mDispatch.setProducerUsage(mDevice, descriptor, toProducerUsage(info.usage));
+        }
+        if (error == GRALLOC1_ERROR_NONE) {
+            error = mDispatch.setConsumerUsage(mDevice, descriptor, toConsumerUsage(info.usage));
+        }
+
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outDescriptor = descriptor;
+        } else {
+            mDispatch.destroyDescriptor(mDevice, descriptor);
+        }
+
+        return toError(error);
+    }
 
     Error allocateOneBuffer(gralloc1_buffer_descriptor_t descriptor,
-                            const native_handle_t** outBuffer, uint32_t* outStride);
+                            const native_handle_t** outBuffer, uint32_t* outStride) {
+        const native_handle_t* buffer = nullptr;
+        int32_t error = mDispatch.allocate(mDevice, 1, &descriptor, &buffer);
+        if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_NOT_SHARED) {
+            return toError(error);
+        }
+
+        uint32_t stride = 0;
+        error = mDispatch.getStride(mDevice, buffer, &stride);
+        if (error != GRALLOC1_ERROR_NONE && error != GRALLOC1_ERROR_UNDEFINED) {
+            mDispatch.release(mDevice, buffer);
+            return toError(error);
+        }
+
+        *outBuffer = buffer;
+        *outStride = stride;
+
+        return Error::NONE;
+    }
 
     gralloc1_device_t* mDevice = nullptr;
 
@@ -88,6 +352,10 @@
     } mDispatch = {};
 };
 
+}  // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::AllocatorHal>;
+
 }  // namespace passthrough
 }  // namespace V2_0
 }  // namespace allocator
diff --git a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
index a0b9503..660099b 100644
--- a/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
+++ b/graphics/allocator/2.0/utils/passthrough/include/allocator-passthrough/2.0/GrallocLoader.h
@@ -16,11 +16,18 @@
 
 #pragma once
 
+#ifndef LOG_TAG
+#warning "GrallocLoader.h included without LOG_TAG"
+#endif
+
 #include <memory>
 
-#include <allocator-hal/2.0/AllocatorHal.h>
-
-struct hw_module_t;
+#include <allocator-hal/2.0/Allocator.h>
+#include <allocator-passthrough/2.0/Gralloc0Hal.h>
+#include <allocator-passthrough/2.0/Gralloc1Hal.h>
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -44,16 +51,45 @@
     }
 
     // load the gralloc module
-    static const hw_module_t* loadModule();
+    static const hw_module_t* loadModule() {
+        const hw_module_t* module;
+        int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        if (error) {
+            ALOGE("failed to get gralloc module");
+            return nullptr;
+        }
+
+        return module;
+    }
 
     // return the major api version of the module
-    static int getModuleMajorApiVersion(const hw_module_t* module);
+    static int getModuleMajorApiVersion(const hw_module_t* module) {
+        return (module->module_api_version >> 8) & 0xff;
+    }
 
     // create an AllocatorHal instance
-    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module);
+    static std::unique_ptr<hal::AllocatorHal> createHal(const hw_module_t* module) {
+        int major = getModuleMajorApiVersion(module);
+        switch (major) {
+            case 1: {
+                auto hal = std::make_unique<Gralloc1Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            case 0: {
+                auto hal = std::make_unique<Gralloc0Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            default:
+                ALOGE("unknown gralloc module major version %d", major);
+                return nullptr;
+        }
+    }
 
     // create an IAllocator instance
-    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal);
+    static IAllocator* createAllocator(std::unique_ptr<hal::AllocatorHal> hal) {
+        auto allocator = std::make_unique<hal::Allocator>();
+        return allocator->init(std::move(hal)) ? allocator.release() : nullptr;
+    }
 };
 
 }  // namespace passthrough
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 40f18c0..92b65a3 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -58,8 +58,8 @@
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.0-vts",
         "libVtsHalGraphicsComposerTestUtils",
-        "libVtsHalGraphicsMapperTestUtils",
         "libnativehelper",
     ],
     header_libs: [
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 9a749d7..376ee37 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -17,10 +17,10 @@
 #define LOG_TAG "graphics_composer_hidl_hal_test"
 
 #include <android-base/logging.h>
+#include <mapper-vts/2.0/MapperVts.h>
 #include "GraphicsComposerCallback.h"
 #include "TestCommandReader.h"
 #include "VtsHalGraphicsComposerTestUtils.h"
-#include "VtsHalGraphicsMapperTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <VtsHalHidlTargetTestEnvBase.h>
@@ -48,7 +48,7 @@
 using android::hardware::graphics::common::V1_0::PixelFormat;
 using android::hardware::graphics::common::V1_0::Transform;
 using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // Test environment for graphics.composer
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
index 0325a6c..78322a1 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -61,10 +61,10 @@
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.0-vts",
         "android.hardware.graphics.mapper@2.1",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsComposerTestUtils@2.2",
-        "libVtsHalGraphicsMapperTestUtils",
         "libnativehelper",
     ],
     header_libs: [
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index 8b44d61..6fbdd3c 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -18,12 +18,12 @@
 
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-vts/2.0/MapperVts.h>
 #include <sync/sync.h>
 #include "2.2/VtsHalGraphicsComposerTestUtils.h"
 #include "GraphicsComposerCallback.h"
 #include "TestCommandReader.h"
 #include "VtsHalGraphicsComposerTestUtils.h"
-#include "VtsHalGraphicsMapperTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -43,7 +43,7 @@
 using android::hardware::graphics::common::V1_0::Transform;
 using android::hardware::graphics::composer::V2_2::IComposerClient;
 using android::hardware::graphics::mapper::V2_0::IMapper;
-using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using android::hardware::graphics::mapper::V2_0::vts::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
 // Test environment for graphics.composer
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 677d966..8874799 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -18,8 +18,10 @@
     defaults: ["hidl_defaults"],
     vendor: true,
     relative_install_path: "hw",
-    srcs: ["GrallocMapper.cpp", "Gralloc0Mapper.cpp", "Gralloc1Mapper.cpp"],
-    cppflags: ["-Wall", "-Wextra"],
+    srcs: ["passthrough.cpp"],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.0-passthrough"
+    ],
     shared_libs: [
         "android.hardware.graphics.mapper@2.0",
         "libbase",
@@ -31,10 +33,5 @@
         "libsync",
         "libutils",
     ],
-}
-
-cc_library_headers {
-    name: "libgrallocmapperincludes",
-    vendor: true,
-    export_include_dirs: ["."],
+    cflags: ["-DLOG_TAG=\"MapperHal\""],
 }
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp b/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
deleted file mode 100644
index 28f5016..0000000
--- a/graphics/mapper/2.0/default/Gralloc0Mapper.cpp
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Gralloc0Mapper"
-
-#include "Gralloc0Mapper.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-Gralloc0Mapper::Gralloc0Mapper(const hw_module_t* module)
-    : mModule(reinterpret_cast<const gralloc_module_t*>(module)),
-      mMinor(module->module_api_version & 0xff) {
-    mCapabilities.highUsageBits = false;
-    mCapabilities.layeredBuffers = false;
-    mCapabilities.unregisterImplyDelete = false;
-}
-
-Error Gralloc0Mapper::registerBuffer(buffer_handle_t bufferHandle) {
-    int result = mModule->registerBuffer(mModule, bufferHandle);
-    return result ? Error::BAD_BUFFER : Error::NONE;
-}
-
-void Gralloc0Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
-    mModule->unregisterBuffer(mModule, bufferHandle);
-}
-
-Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
-                                 uint64_t cpuUsage,
-                                 const IMapper::Rect& accessRegion, int fenceFd,
-                                 void** outData) {
-    int result;
-    void* data = nullptr;
-    if (mMinor >= 3 && mModule->lockAsync) {
-        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
-        // gralloc's responsibility to close it, even on locking errors.
-        if (fenceFd >= 0) {
-            fenceFd = dup(fenceFd);
-            if (fenceFd < 0) {
-                return Error::NO_RESOURCES;
-            }
-        }
-
-        result = mModule->lockAsync(mModule, bufferHandle, cpuUsage,
-                                    accessRegion.left, accessRegion.top,
-                                    accessRegion.width, accessRegion.height,
-                                    &data, fenceFd);
-    } else {
-        waitFenceFd(fenceFd, "Gralloc0Mapper::lock");
-
-        result = mModule->lock(mModule, bufferHandle, cpuUsage,
-                               accessRegion.left, accessRegion.top,
-                               accessRegion.width, accessRegion.height, &data);
-    }
-
-    if (result) {
-        return Error::BAD_VALUE;
-    } else {
-        *outData = data;
-        return Error::NONE;
-    }
-}
-
-Error Gralloc0Mapper::lockBuffer(buffer_handle_t bufferHandle,
-                                 uint64_t cpuUsage,
-                                 const IMapper::Rect& accessRegion, int fenceFd,
-                                 YCbCrLayout* outLayout) {
-    int result;
-    android_ycbcr ycbcr = {};
-    if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
-        // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
-        // gralloc's responsibility to close it, even on locking errors.
-        if (fenceFd >= 0) {
-            fenceFd = dup(fenceFd);
-            if (fenceFd < 0) {
-                return Error::NO_RESOURCES;
-            }
-        }
-
-        result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage,
-                                          accessRegion.left, accessRegion.top,
-                                          accessRegion.width,
-                                          accessRegion.height, &ycbcr, fenceFd);
-    } else {
-        waitFenceFd(fenceFd, "Gralloc0Mapper::lockYCbCr");
-
-        if (mModule->lock_ycbcr) {
-            result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage,
-                                         accessRegion.left, accessRegion.top,
-                                         accessRegion.width,
-                                         accessRegion.height, &ycbcr);
-        } else {
-            result = -EINVAL;
-        }
-    }
-
-    if (result) {
-        return Error::BAD_VALUE;
-    } else {
-        outLayout->y = ycbcr.y;
-        outLayout->cb = ycbcr.cb;
-        outLayout->cr = ycbcr.cr;
-        outLayout->yStride = ycbcr.ystride;
-        outLayout->cStride = ycbcr.cstride;
-        outLayout->chromaStep = ycbcr.chroma_step;
-        return Error::NONE;
-    }
-}
-
-Error Gralloc0Mapper::unlockBuffer(buffer_handle_t bufferHandle,
-                                   int* outFenceFd) {
-    int result;
-    int fenceFd = -1;
-    if (mMinor >= 3 && mModule->unlockAsync) {
-        result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
-    } else {
-        result = mModule->unlock(mModule, bufferHandle);
-    }
-
-    if (result) {
-        // we always own the fenceFd even when unlock failed
-        if (fenceFd >= 0) {
-            close(fenceFd);
-        }
-
-        return Error::BAD_VALUE;
-    } else {
-        *outFenceFd = fenceFd;
-        return Error::NONE;
-    }
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace mapper
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc0Mapper.h b/graphics/mapper/2.0/default/Gralloc0Mapper.h
deleted file mode 100644
index e792a69..0000000
--- a/graphics/mapper/2.0/default/Gralloc0Mapper.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
-
-#include "GrallocMapper.h"
-
-#include <hardware/gralloc.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class Gralloc0Mapper : public GrallocMapper {
-   public:
-    Gralloc0Mapper(const hw_module_t* module);
-
-   private:
-    Error registerBuffer(buffer_handle_t bufferHandle) override;
-    void unregisterBuffer(buffer_handle_t bufferHandle) override;
-    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                     const IMapper::Rect& accessRegion, int fenceFd,
-                     void** outData) override;
-    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                     const IMapper::Rect& accessRegion, int fenceFd,
-                     YCbCrLayout* outLayout) override;
-    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
-
-    const gralloc_module_t* mModule;
-    uint8_t mMinor;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace mapper
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC0MAPPER_H
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp b/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
deleted file mode 100644
index c1e5adc..0000000
--- a/graphics/mapper/2.0/default/Gralloc1Mapper.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "Gralloc1Mapper"
-
-#include "Gralloc1Mapper.h"
-
-#include <vector>
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-
-Gralloc1Mapper::Gralloc1Mapper(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch() {
-    int result = gralloc1_open(module, &mDevice);
-    if (result) {
-        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
-                         strerror(-result));
-    }
-
-    initCapabilities();
-    initDispatch();
-}
-
-Gralloc1Mapper::~Gralloc1Mapper() {
-    gralloc1_close(mDevice);
-}
-
-void Gralloc1Mapper::initCapabilities() {
-    mCapabilities.highUsageBits = true;
-    mCapabilities.layeredBuffers = false;
-    mCapabilities.unregisterImplyDelete = false;
-
-    uint32_t count = 0;
-    mDevice->getCapabilities(mDevice, &count, nullptr);
-
-    std::vector<int32_t> capabilities(count);
-    mDevice->getCapabilities(mDevice, &count, capabilities.data());
-    capabilities.resize(count);
-
-    for (auto capability : capabilities) {
-        switch (capability) {
-            case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
-                mCapabilities.layeredBuffers = true;
-                break;
-            case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
-                mCapabilities.unregisterImplyDelete = true;
-                break;
-        }
-    }
-}
-
-template <typename T>
-void Gralloc1Mapper::initDispatch(gralloc1_function_descriptor_t desc,
-                                  T* outPfn) {
-    auto pfn = mDevice->getFunction(mDevice, desc);
-    if (!pfn) {
-        LOG_ALWAYS_FATAL("failed to get gralloc1 function %d", desc);
-    }
-
-    *outPfn = reinterpret_cast<T>(pfn);
-}
-
-void Gralloc1Mapper::initDispatch() {
-    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
-    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
-    initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES,
-                 &mDispatch.getNumFlexPlanes);
-    initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock);
-    initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex);
-    initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock);
-}
-
-Error Gralloc1Mapper::toError(int32_t error) {
-    switch (error) {
-        case GRALLOC1_ERROR_NONE:
-            return Error::NONE;
-        case GRALLOC1_ERROR_BAD_DESCRIPTOR:
-            return Error::BAD_DESCRIPTOR;
-        case GRALLOC1_ERROR_BAD_HANDLE:
-            return Error::BAD_BUFFER;
-        case GRALLOC1_ERROR_BAD_VALUE:
-            return Error::BAD_VALUE;
-        case GRALLOC1_ERROR_NOT_SHARED:
-            return Error::NONE;  // this is fine
-        case GRALLOC1_ERROR_NO_RESOURCES:
-            return Error::NO_RESOURCES;
-        case GRALLOC1_ERROR_UNDEFINED:
-        case GRALLOC1_ERROR_UNSUPPORTED:
-        default:
-            return Error::UNSUPPORTED;
-    }
-}
-
-bool Gralloc1Mapper::toYCbCrLayout(const android_flex_layout& flex,
-                                   YCbCrLayout* outLayout) {
-    // must be YCbCr
-    if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
-        return false;
-    }
-
-    for (int i = 0; i < 3; i++) {
-        const auto& plane = flex.planes[i];
-        // must have 8-bit depth
-        if (plane.bits_per_component != 8 || plane.bits_used != 8) {
-            return false;
-        }
-
-        if (plane.component == FLEX_COMPONENT_Y) {
-            // Y must not be interleaved
-            if (plane.h_increment != 1) {
-                return false;
-            }
-        } else {
-            // Cb and Cr can be interleaved
-            if (plane.h_increment != 1 && plane.h_increment != 2) {
-                return false;
-            }
-        }
-
-        if (!plane.v_increment) {
-            return false;
-        }
-    }
-
-    if (flex.planes[0].component != FLEX_COMPONENT_Y ||
-        flex.planes[1].component != FLEX_COMPONENT_Cb ||
-        flex.planes[2].component != FLEX_COMPONENT_Cr) {
-        return false;
-    }
-
-    const auto& y = flex.planes[0];
-    const auto& cb = flex.planes[1];
-    const auto& cr = flex.planes[2];
-
-    if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
-        return false;
-    }
-
-    outLayout->y = y.top_left;
-    outLayout->cb = cb.top_left;
-    outLayout->cr = cr.top_left;
-    outLayout->yStride = y.v_increment;
-    outLayout->cStride = cb.v_increment;
-    outLayout->chromaStep = cb.h_increment;
-
-    return true;
-}
-
-gralloc1_rect_t Gralloc1Mapper::asGralloc1Rect(const IMapper::Rect& rect) {
-    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
-}
-
-Error Gralloc1Mapper::registerBuffer(buffer_handle_t bufferHandle) {
-    return toError(mDispatch.retain(mDevice, bufferHandle));
-}
-
-void Gralloc1Mapper::unregisterBuffer(buffer_handle_t bufferHandle) {
-    mDispatch.release(mDevice, bufferHandle);
-}
-
-Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
-                                 uint64_t cpuUsage,
-                                 const IMapper::Rect& accessRegion, int fenceFd,
-                                 void** outData) {
-    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
-    // gralloc's responsibility to close it, even on locking errors.
-    if (fenceFd >= 0) {
-        fenceFd = dup(fenceFd);
-        if (fenceFd < 0) {
-            return Error::NO_RESOURCES;
-        }
-    }
-
-    const uint64_t consumerUsage =
-        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
-    const auto accessRect = asGralloc1Rect(accessRegion);
-    void* data = nullptr;
-    int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage,
-                                   consumerUsage, &accessRect, &data, fenceFd);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outData = data;
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Mapper::lockBuffer(buffer_handle_t bufferHandle,
-                                 uint64_t cpuUsage,
-                                 const IMapper::Rect& accessRegion, int fenceFd,
-                                 YCbCrLayout* outLayout) {
-    // prepare flex layout
-    android_flex_layout flex = {};
-    int32_t error =
-        mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
-    if (error != GRALLOC1_ERROR_NONE) {
-        return toError(error);
-    }
-    std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
-    flex.planes = flexPlanes.data();
-
-    // Dup fenceFd as it is going to be owned by gralloc.  Note that it is
-    // gralloc's responsibility to close it, even on locking errors.
-    if (fenceFd >= 0) {
-        fenceFd = dup(fenceFd);
-        if (fenceFd < 0) {
-            return Error::NO_RESOURCES;
-        }
-    }
-
-    const uint64_t consumerUsage =
-        cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
-    const auto accessRect = asGralloc1Rect(accessRegion);
-    error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage,
-                               &accessRect, &flex, fenceFd);
-    if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
-        ALOGD("unable to convert android_flex_layout to YCbCrLayout");
-
-        // undo the lock
-        fenceFd = -1;
-        mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
-        if (fenceFd >= 0) {
-            close(fenceFd);
-        }
-
-        error = GRALLOC1_ERROR_BAD_HANDLE;
-    }
-
-    return toError(error);
-}
-
-Error Gralloc1Mapper::unlockBuffer(buffer_handle_t bufferHandle,
-                                   int* outFenceFd) {
-    int fenceFd = -1;
-    int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
-
-    if (error == GRALLOC1_ERROR_NONE) {
-        *outFenceFd = fenceFd;
-    } else if (fenceFd >= 0) {
-        // we always own the fenceFd even when unlock failed
-        close(fenceFd);
-    }
-
-    return toError(error);
-}
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace mapper
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
diff --git a/graphics/mapper/2.0/default/Gralloc1Mapper.h b/graphics/mapper/2.0/default/Gralloc1Mapper.h
deleted file mode 100644
index 452afdf..0000000
--- a/graphics/mapper/2.0/default/Gralloc1Mapper.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
-
-#include "GrallocMapper.h"
-
-#include <hardware/gralloc1.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class Gralloc1Mapper : public GrallocMapper {
-   public:
-    Gralloc1Mapper(const hw_module_t* module);
-    ~Gralloc1Mapper();
-
-   private:
-    void initCapabilities();
-
-    template <typename T>
-    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
-    void initDispatch();
-
-    static Error toError(int32_t error);
-    static bool toYCbCrLayout(const android_flex_layout& flex,
-                              YCbCrLayout* outLayout);
-    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
-
-    Error registerBuffer(buffer_handle_t bufferHandle) override;
-    void unregisterBuffer(buffer_handle_t bufferHandle) override;
-    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                     const IMapper::Rect& accessRegion, int fenceFd,
-                     void** outData) override;
-    Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                     const IMapper::Rect& accessRegion, int fenceFd,
-                     YCbCrLayout* outLayout) override;
-    Error unlockBuffer(buffer_handle_t bufferHandle, int* outFenceFd) override;
-
-    gralloc1_device_t* mDevice;
-
-    struct {
-        GRALLOC1_PFN_RETAIN retain;
-        GRALLOC1_PFN_RELEASE release;
-        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
-        GRALLOC1_PFN_LOCK lock;
-        GRALLOC1_PFN_LOCK_FLEX lockFlex;
-        GRALLOC1_PFN_UNLOCK unlock;
-    } mDispatch;
-};
-
-}  // namespace implementation
-}  // namespace V2_0
-}  // namespace mapper
-}  // namespace graphics
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC1MAPPER_H
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
deleted file mode 100644
index d16143d..0000000
--- a/graphics/mapper/2.0/default/GrallocMapper.cpp
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- * * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocMapperPassthrough"
-
-#include "GrallocMapper.h"
-
-#include "Gralloc0Mapper.h"
-#include "Gralloc1Mapper.h"
-#include "GrallocBufferDescriptor.h"
-
-#include <inttypes.h>
-
-#include <log/log.h>
-#include <sync/sync.h>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::PixelFormat;
-
-namespace {
-
-class RegisteredHandlePool {
-   public:
-    bool add(buffer_handle_t bufferHandle) {
-        std::lock_guard<std::mutex> lock(mMutex);
-        return mHandles.insert(bufferHandle).second;
-    }
-
-    native_handle_t* pop(void* buffer) {
-        auto bufferHandle = static_cast<native_handle_t*>(buffer);
-
-        std::lock_guard<std::mutex> lock(mMutex);
-        return mHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
-    }
-
-    buffer_handle_t get(const void* buffer) {
-        auto bufferHandle = static_cast<buffer_handle_t>(buffer);
-
-        std::lock_guard<std::mutex> lock(mMutex);
-        return mHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
-    }
-
-   private:
-    std::mutex mMutex;
-    std::unordered_set<buffer_handle_t> mHandles;
-};
-
-// GraphicBufferMapper is expected to be valid (and leaked) during process
-// termination.  We need to make sure IMapper, and in turn, gRegisteredHandles
-// are valid as well.  Create the registered handle pool on the heap, and let
-// it leak for simplicity.
-//
-// However, there is no way to make sure gralloc0/gralloc1 are valid.  Any use
-// of static/global object in gralloc0/gralloc1 that may have been destructed
-// is potentially broken.
-RegisteredHandlePool* gRegisteredHandles = new RegisteredHandlePool;
-
-}  // anonymous namespace
-
-bool GrallocMapper::validateDescriptorInfo(
-    const BufferDescriptorInfo& descriptorInfo) const {
-    const uint64_t validUsageBits =
-        BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK |
-        BufferUsage::GPU_TEXTURE | BufferUsage::GPU_RENDER_TARGET |
-        BufferUsage::COMPOSER_OVERLAY | BufferUsage::COMPOSER_CLIENT_TARGET |
-        BufferUsage::PROTECTED | BufferUsage::COMPOSER_CURSOR |
-        BufferUsage::VIDEO_ENCODER | BufferUsage::CAMERA_OUTPUT |
-        BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
-        BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
-        BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
-        (mCapabilities.highUsageBits ? BufferUsage::VENDOR_MASK_HI
-                                     : static_cast<BufferUsage>(0));
-
-    if (!descriptorInfo.width || !descriptorInfo.height ||
-        !descriptorInfo.layerCount) {
-        return false;
-    }
-
-    if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount > 1) {
-        return false;
-    }
-
-    if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
-        return false;
-    }
-
-    if (descriptorInfo.usage & ~validUsageBits) {
-        // could not fail as gralloc may use the reserved bits...
-        ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
-              descriptorInfo.usage & ~validUsageBits);
-    }
-
-    return true;
-}
-
-Return<void> GrallocMapper::createDescriptor(
-    const BufferDescriptorInfo& descriptorInfo, createDescriptor_cb hidl_cb) {
-    if (validateDescriptorInfo(descriptorInfo)) {
-        hidl_cb(Error::NONE, grallocEncodeBufferDescriptor(descriptorInfo));
-    } else {
-        hidl_cb(Error::BAD_VALUE, BufferDescriptor());
-    }
-
-    return Void();
-}
-
-Return<void> GrallocMapper::importBuffer(const hidl_handle& rawHandle,
-                                         importBuffer_cb hidl_cb) {
-    // because of passthrough HALs, we must not generate an error when
-    // rawHandle has been imported
-
-    if (!rawHandle.getNativeHandle()) {
-        hidl_cb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    native_handle_t* bufferHandle =
-        native_handle_clone(rawHandle.getNativeHandle());
-    if (!bufferHandle) {
-        hidl_cb(Error::NO_RESOURCES, nullptr);
-        return Void();
-    }
-
-    Error error = registerBuffer(bufferHandle);
-    if (error != Error::NONE) {
-        native_handle_close(bufferHandle);
-        native_handle_delete(bufferHandle);
-
-        hidl_cb(error, nullptr);
-        return Void();
-    }
-
-    // The newly cloned handle is already registered?  This can only happen
-    // when a handle previously registered was native_handle_delete'd instead
-    // of freeBuffer'd.
-    if (!gRegisteredHandles->add(bufferHandle)) {
-        ALOGE("handle %p has already been imported; potential fd leaking",
-              bufferHandle);
-        unregisterBuffer(bufferHandle);
-        if (!mCapabilities.unregisterImplyDelete) {
-            native_handle_close(bufferHandle);
-            native_handle_delete(bufferHandle);
-        }
-
-        hidl_cb(Error::NO_RESOURCES, nullptr);
-        return Void();
-    }
-
-    hidl_cb(Error::NONE, bufferHandle);
-    return Void();
-}
-
-Return<Error> GrallocMapper::freeBuffer(void* buffer) {
-    native_handle_t* bufferHandle = gRegisteredHandles->pop(buffer);
-    if (!bufferHandle) {
-        return Error::BAD_BUFFER;
-    }
-
-    unregisterBuffer(bufferHandle);
-    if (!mCapabilities.unregisterImplyDelete) {
-        native_handle_close(bufferHandle);
-        native_handle_delete(bufferHandle);
-    }
-
-    return Error::NONE;
-}
-
-void GrallocMapper::waitFenceFd(int fenceFd, const char* logname) {
-    if (fenceFd < 0) {
-        return;
-    }
-
-    const int warningTimeout = 3500;
-    const int error = sync_wait(fenceFd, warningTimeout);
-    if (error < 0 && errno == ETIME) {
-        ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd,
-              warningTimeout);
-        sync_wait(fenceFd, -1);
-    }
-}
-
-bool GrallocMapper::getFenceFd(const hidl_handle& fenceHandle,
-                               int* outFenceFd) {
-    auto handle = fenceHandle.getNativeHandle();
-    if (handle && handle->numFds > 1) {
-        ALOGE("invalid fence handle with %d fds", handle->numFds);
-        return false;
-    }
-
-    *outFenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
-    return true;
-}
-
-hidl_handle GrallocMapper::getFenceHandle(int fenceFd, char* handleStorage) {
-    native_handle_t* handle = nullptr;
-    if (fenceFd >= 0) {
-        handle = native_handle_init(handleStorage, 1, 0);
-        handle->data[0] = fenceFd;
-    }
-
-    return hidl_handle(handle);
-}
-
-Return<void> GrallocMapper::lock(void* buffer, uint64_t cpuUsage,
-                                 const IMapper::Rect& accessRegion,
-                                 const hidl_handle& acquireFence,
-                                 lock_cb hidl_cb) {
-    buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
-    if (!bufferHandle) {
-        hidl_cb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    int fenceFd;
-    if (!getFenceFd(acquireFence, &fenceFd)) {
-        hidl_cb(Error::BAD_VALUE, nullptr);
-        return Void();
-    }
-
-    void* data = nullptr;
-    Error error =
-        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &data);
-
-    hidl_cb(error, data);
-    return Void();
-}
-
-Return<void> GrallocMapper::lockYCbCr(void* buffer, uint64_t cpuUsage,
-                                      const IMapper::Rect& accessRegion,
-                                      const hidl_handle& acquireFence,
-                                      lockYCbCr_cb hidl_cb) {
-    YCbCrLayout layout = {};
-
-    buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
-    if (!bufferHandle) {
-        hidl_cb(Error::BAD_BUFFER, layout);
-        return Void();
-    }
-
-    int fenceFd;
-    if (!getFenceFd(acquireFence, &fenceFd)) {
-        hidl_cb(Error::BAD_VALUE, layout);
-        return Void();
-    }
-
-    Error error =
-        lockBuffer(bufferHandle, cpuUsage, accessRegion, fenceFd, &layout);
-
-    hidl_cb(error, layout);
-    return Void();
-}
-
-Return<void> GrallocMapper::unlock(void* buffer, unlock_cb hidl_cb) {
-    buffer_handle_t bufferHandle = gRegisteredHandles->get(buffer);
-    if (!bufferHandle) {
-        hidl_cb(Error::BAD_BUFFER, nullptr);
-        return Void();
-    }
-
-    int fenceFd;
-    Error error = unlockBuffer(bufferHandle, &fenceFd);
-    if (error == Error::NONE) {
-        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
-
-        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
-
-        if (fenceFd >= 0) {
-            close(fenceFd);
-        }
-    } else {
-        hidl_cb(error, nullptr);
-    }
-
-    return Void();
-}
-
-IMapper* HIDL_FETCH_IMapper(const char* /* name */) {
-    const hw_module_t* module = nullptr;
-    int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
-    if (err) {
-        ALOGE("failed to get gralloc module");
-        return nullptr;
-    }
-
-    uint8_t major = (module->module_api_version >> 8) & 0xff;
-    switch (major) {
-        case 1:
-            return new Gralloc1Mapper(module);
-        case 0:
-            return new Gralloc0Mapper(module);
-        default:
-            ALOGE("unknown gralloc module major version %d", major);
-            return nullptr;
-    }
-}
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
diff --git a/graphics/mapper/2.0/default/GrallocMapper.h b/graphics/mapper/2.0/default/GrallocMapper.h
deleted file mode 100644
index e876fe4..0000000
--- a/graphics/mapper/2.0/default/GrallocMapper.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
-
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-#include <cutils/native_handle.h>
-
-#include <mutex>
-#include <unordered_set>
-
-namespace android {
-namespace hardware {
-namespace graphics {
-namespace mapper {
-namespace V2_0 {
-namespace implementation {
-
-class GrallocMapper : public IMapper {
-   public:
-    // IMapper interface
-    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
-                                  createDescriptor_cb hidl_cb) override;
-    Return<void> importBuffer(const hidl_handle& rawHandle,
-                              importBuffer_cb hidl_cb) override;
-    Return<Error> freeBuffer(void* buffer) override;
-    Return<void> lock(void* buffer, uint64_t cpuUsage,
-                      const IMapper::Rect& accessRegion,
-                      const hidl_handle& acquireFence,
-                      lock_cb hidl_cb) override;
-    Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage,
-                           const IMapper::Rect& accessRegion,
-                           const hidl_handle& acquireFence,
-                           lockYCbCr_cb hidl_cb) override;
-    Return<void> unlock(void* buffer, unlock_cb hidl_cb) override;
-
-   protected:
-    static void waitFenceFd(int fenceFd, const char* logname);
-
-    struct {
-        bool highUsageBits;
-        bool layeredBuffers;
-        bool unregisterImplyDelete;
-    } mCapabilities = {};
-
-   private:
-    virtual bool validateDescriptorInfo(
-        const BufferDescriptorInfo& descriptorInfo) const;
-
-    // Register a buffer.  The handle is already cloned by the caller.
-    virtual Error registerBuffer(buffer_handle_t bufferHandle) = 0;
-
-    // Unregister a buffer.  The handle is closed and deleted by the
-    // callee if and only if mCapabilities.unregisterImplyDelete is set.
-    virtual void unregisterBuffer(buffer_handle_t bufferHandle) = 0;
-
-    // Lock a buffer.  The fence is owned by the caller.
-    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                             const IMapper::Rect& accessRegion, int fenceFd,
-                             void** outData) = 0;
-    virtual Error lockBuffer(buffer_handle_t bufferHandle, uint64_t cpuUsage,
-                             const IMapper::Rect& accessRegion, int fenceFd,
-                             YCbCrLayout* outLayout) = 0;
-
-    // Unlock a buffer.  The returned fence is owned by the caller.
-    virtual Error unlockBuffer(buffer_handle_t bufferHandle,
-                               int* outFenceFd) = 0;
-
-    static bool getFenceFd(const hidl_handle& fenceHandle, int* outFenceFd);
-    static hidl_handle getFenceHandle(int fenceFd, char* handleStorage);
-};
-
-extern "C" IMapper* HIDL_FETCH_IMapper(const char* name);
-
-} // namespace implementation
-} // namespace V2_0
-} // namespace mapper
-} // namespace graphics
-} // namespace hardware
-} // namespace android
-
-#endif // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOC_MAPPER_H
diff --git a/graphics/mapper/2.0/default/passthrough.cpp b/graphics/mapper/2.0/default/passthrough.cpp
new file mode 100644
index 0000000..e18b88f
--- /dev/null
+++ b/graphics/mapper/2.0/default/passthrough.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <mapper-passthrough/2.0/GrallocLoader.h>
+
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::passthrough::GrallocLoader;
+
+extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
+    return GrallocLoader::load();
+}
diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.0/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.0/utils/hal/Android.bp b/graphics/mapper/2.0/utils/hal/Android.bp
new file mode 100644
index 0000000..5610a69
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.0-hal",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
new file mode 100644
index 0000000..5ad2a65
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
@@ -0,0 +1,210 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Mapper.h included without LOG_TAG"
+#endif
+
+#include <memory>
+
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace hal {
+
+namespace detail {
+
+// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
+template <typename Interface, typename Hal>
+class MapperImpl : public Interface {
+   public:
+    bool init(std::unique_ptr<Hal> hal) {
+        mHal = std::move(hal);
+        return true;
+    }
+
+    // IMapper 2.0 interface
+
+    Return<void> createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
+                                  IMapper::createDescriptor_cb hidl_cb) override {
+        BufferDescriptor descriptor;
+        Error error = mHal->createDescriptor(descriptorInfo, &descriptor);
+        hidl_cb(error, descriptor);
+        return Void();
+    }
+
+    Return<void> importBuffer(const hidl_handle& rawHandle,
+                              IMapper::importBuffer_cb hidl_cb) override {
+        if (!rawHandle.getNativeHandle()) {
+            hidl_cb(Error::BAD_BUFFER, nullptr);
+            return Void();
+        }
+
+        native_handle_t* bufferHandle = nullptr;
+        Error error = mHal->importBuffer(rawHandle.getNativeHandle(), &bufferHandle);
+        if (error != Error::NONE) {
+            hidl_cb(error, nullptr);
+            return Void();
+        }
+
+        void* buffer = addImportedBuffer(bufferHandle);
+        if (!buffer) {
+            mHal->freeBuffer(bufferHandle);
+            hidl_cb(Error::NO_RESOURCES, nullptr);
+            return Void();
+        }
+
+        hidl_cb(error, buffer);
+        return Void();
+    }
+
+    Return<Error> freeBuffer(void* buffer) override {
+        native_handle_t* bufferHandle = removeImportedBuffer(buffer);
+        if (!bufferHandle) {
+            return Error::BAD_BUFFER;
+        }
+
+        return mHal->freeBuffer(bufferHandle);
+    }
+
+    Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
+                      const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
+        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        if (!bufferHandle) {
+            hidl_cb(Error::BAD_BUFFER, nullptr);
+            return Void();
+        }
+
+        base::unique_fd fenceFd;
+        Error error = getFenceFd(acquireFence, &fenceFd);
+        if (error != Error::NONE) {
+            hidl_cb(error, nullptr);
+            return Void();
+        }
+
+        void* data = nullptr;
+        error = mHal->lock(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &data);
+        hidl_cb(error, data);
+        return Void();
+    }
+
+    Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
+                           const hidl_handle& acquireFence,
+                           IMapper::lockYCbCr_cb hidl_cb) override {
+        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        if (!bufferHandle) {
+            hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
+            return Void();
+        }
+
+        base::unique_fd fenceFd;
+        Error error = getFenceFd(acquireFence, &fenceFd);
+        if (error != Error::NONE) {
+            hidl_cb(error, YCbCrLayout{});
+            return Void();
+        }
+
+        YCbCrLayout layout{};
+        error = mHal->lockYCbCr(bufferHandle, cpuUsage, accessRegion, std::move(fenceFd), &layout);
+        hidl_cb(error, layout);
+        return Void();
+    }
+
+    Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
+        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        if (!bufferHandle) {
+            hidl_cb(Error::BAD_BUFFER, nullptr);
+            return Void();
+        }
+
+        base::unique_fd fenceFd;
+        Error error = mHal->unlock(bufferHandle, &fenceFd);
+        if (error != Error::NONE) {
+            hidl_cb(error, nullptr);
+            return Void();
+        }
+
+        NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+        hidl_cb(error, getFenceHandle(fenceFd, fenceStorage));
+        return Void();
+    }
+
+   protected:
+    // these functions can be overriden to do true imported buffer management
+    virtual void* addImportedBuffer(native_handle_t* bufferHandle) {
+        return static_cast<void*>(bufferHandle);
+    }
+
+    virtual native_handle_t* removeImportedBuffer(void* buffer) {
+        return static_cast<native_handle_t*>(buffer);
+    }
+
+    virtual const native_handle_t* getImportedBuffer(void* buffer) const {
+        return static_cast<const native_handle_t*>(buffer);
+    }
+
+    // convert fenceFd to or from hidl_handle
+    static Error getFenceFd(const hidl_handle& fenceHandle, base::unique_fd* outFenceFd) {
+        auto handle = fenceHandle.getNativeHandle();
+        if (handle && handle->numFds > 1) {
+            ALOGE("invalid fence handle with %d fds", handle->numFds);
+            return Error::BAD_VALUE;
+        }
+
+        int fenceFd = (handle && handle->numFds == 1) ? handle->data[0] : -1;
+        if (fenceFd >= 0) {
+            fenceFd = dup(fenceFd);
+            if (fenceFd < 0) {
+                return Error::NO_RESOURCES;
+            }
+        }
+
+        outFenceFd->reset(fenceFd);
+
+        return Error::NONE;
+    }
+
+    static hidl_handle getFenceHandle(const base::unique_fd& fenceFd, char* handleStorage) {
+        native_handle_t* handle = nullptr;
+        if (fenceFd >= 0) {
+            handle = native_handle_init(handleStorage, 1, 0);
+            handle->data[0] = fenceFd;
+        }
+
+        return hidl_handle(handle);
+    }
+
+    std::unique_ptr<Hal> mHal;
+};
+
+}  // namespace detail
+
+using Mapper = detail::MapperImpl<IMapper, MapperHal>;
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h
new file mode 100644
index 0000000..ab2e5cf
--- /dev/null
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/MapperHal.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/unique_fd.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace hal {
+
+class MapperHal {
+   public:
+    virtual ~MapperHal() = default;
+
+    // create a BufferDescriptor
+    virtual Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                   BufferDescriptor* outDescriptor) = 0;
+
+    // import a raw handle owned by the caller
+    virtual Error importBuffer(const native_handle_t* rawHandle,
+                               native_handle_t** outBufferHandle) = 0;
+
+    // free an imported buffer handle
+    virtual Error freeBuffer(native_handle_t* bufferHandle) = 0;
+
+    // lock a buffer
+    virtual Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                       const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                       void** outData) = 0;
+
+    // lock a YCbCr buffer
+    virtual Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                            const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                            YCbCrLayout* outLayout) = 0;
+
+    // unlock a buffer
+    virtual Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/Android.bp b/graphics/mapper/2.0/utils/passthrough/Android.bp
new file mode 100644
index 0000000..4f700c8
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/Android.bp
@@ -0,0 +1,43 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.0-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+        "libsync",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.mapper@2.0",
+        "libhardware",
+        "libsync",
+    ],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+}
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.0-passthrough_headers",
+    vendor: true,
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
new file mode 100644
index 0000000..7369ac7
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc0Hal.h
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc0Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <hardware/gralloc.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+#include <sync/sync.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public Hal {
+   public:
+    bool initWithModule(const hw_module_t* module) {
+        mModule = reinterpret_cast<const gralloc_module_t*>(module);
+        mMinor = module->module_api_version & 0xff;
+        return true;
+    }
+
+    Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                           BufferDescriptor* outDescriptor) override {
+        if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+            return Error::BAD_VALUE;
+        }
+
+        if (descriptorInfo.layerCount != 1) {
+            return Error::UNSUPPORTED;
+        }
+
+        if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+            return Error::BAD_VALUE;
+        }
+
+        const uint64_t validUsageBits = getValidBufferUsageMask();
+        if (descriptorInfo.usage & ~validUsageBits) {
+            ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+                  descriptorInfo.usage & ~validUsageBits);
+        }
+
+        *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+        return Error::NONE;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle,
+                       native_handle_t** outBufferHandle) override {
+        native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+        if (!bufferHandle) {
+            return Error::NO_RESOURCES;
+        }
+
+        if (mModule->registerBuffer(mModule, bufferHandle)) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+            return Error::BAD_BUFFER;
+        }
+
+        *outBufferHandle = bufferHandle;
+
+        return Error::NONE;
+    }
+
+    Error freeBuffer(native_handle_t* bufferHandle) override {
+        if (mModule->unregisterBuffer(mModule, bufferHandle)) {
+            return Error::BAD_BUFFER;
+        }
+
+        native_handle_close(bufferHandle);
+        native_handle_delete(bufferHandle);
+        return Error::NONE;
+    }
+
+    Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+               void** outData) override {
+        int result;
+        void* data = nullptr;
+        if (mMinor >= 3 && mModule->lockAsync) {
+            result = mModule->lockAsync(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                        accessRegion.top, accessRegion.width, accessRegion.height,
+                                        &data, fenceFd.release());
+        } else {
+            waitFenceFd(fenceFd, "Gralloc0Hal::lock");
+
+            result =
+                mModule->lock(mModule, bufferHandle, cpuUsage, accessRegion.left, accessRegion.top,
+                              accessRegion.width, accessRegion.height, &data);
+        }
+
+        if (result) {
+            return Error::BAD_VALUE;
+        }
+
+        *outData = data;
+        return Error::NONE;
+    }
+
+    Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                    YCbCrLayout* outLayout) override {
+        int result;
+        android_ycbcr ycbcr = {};
+        if (mMinor >= 3 && mModule->lockAsync_ycbcr) {
+            result = mModule->lockAsync_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                              accessRegion.top, accessRegion.width,
+                                              accessRegion.height, &ycbcr, fenceFd.release());
+        } else {
+            waitFenceFd(fenceFd, "Gralloc0Hal::lockYCbCr");
+
+            if (mModule->lock_ycbcr) {
+                result = mModule->lock_ycbcr(mModule, bufferHandle, cpuUsage, accessRegion.left,
+                                             accessRegion.top, accessRegion.width,
+                                             accessRegion.height, &ycbcr);
+            } else {
+                result = -EINVAL;
+            }
+        }
+
+        if (result) {
+            return Error::BAD_VALUE;
+        }
+
+        outLayout->y = ycbcr.y;
+        outLayout->cb = ycbcr.cb;
+        outLayout->cr = ycbcr.cr;
+        outLayout->yStride = ycbcr.ystride;
+        outLayout->cStride = ycbcr.cstride;
+        outLayout->chromaStep = ycbcr.chroma_step;
+        return Error::NONE;
+    }
+
+    Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+        int result;
+        int fenceFd = -1;
+        if (mMinor >= 3 && mModule->unlockAsync) {
+            result = mModule->unlockAsync(mModule, bufferHandle, &fenceFd);
+        } else {
+            result = mModule->unlock(mModule, bufferHandle);
+        }
+
+        // we always own the fenceFd even when unlock failed
+        outFenceFd->reset(fenceFd);
+        return result ? Error::BAD_VALUE : Error::NONE;
+    }
+
+   protected:
+    virtual uint64_t getValidBufferUsageMask() const {
+        return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+               BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+               BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+               BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+               BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+               BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+               BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK;
+    }
+
+    static void waitFenceFd(const base::unique_fd& fenceFd, const char* logname) {
+        if (fenceFd < 0) {
+            return;
+        }
+
+        const int warningTimeout = 3500;
+        const int error = sync_wait(fenceFd, warningTimeout);
+        if (error < 0 && errno == ETIME) {
+            ALOGE("%s: fence %d didn't signal in %u ms", logname, fenceFd.get(), warningTimeout);
+            sync_wait(fenceFd, -1);
+        }
+    }
+
+    const gralloc_module_t* mModule = nullptr;
+    uint8_t mMinor = 0;
+};
+
+}  // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
new file mode 100644
index 0000000..d9beb4f
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Gralloc1Hal.h included without LOG_TAG"
+#endif
+
+#include <inttypes.h>
+
+#include <vector>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocBufferDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+namespace detail {
+
+using common::V1_0::BufferUsage;
+
+// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public Hal {
+   public:
+    ~Gralloc1HalImpl() {
+        if (mDevice) {
+            gralloc1_close(mDevice);
+        }
+    }
+
+    bool initWithModule(const hw_module_t* module) {
+        int result = gralloc1_open(module, &mDevice);
+        if (result) {
+            ALOGE("failed to open gralloc1 device: %s", strerror(-result));
+            mDevice = nullptr;
+            return false;
+        }
+
+        initCapabilities();
+
+        if (!initDispatch()) {
+            gralloc1_close(mDevice);
+            mDevice = nullptr;
+            return false;
+        }
+
+        return true;
+    }
+
+    Error createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                           BufferDescriptor* outDescriptor) override {
+        if (!descriptorInfo.width || !descriptorInfo.height || !descriptorInfo.layerCount) {
+            return Error::BAD_VALUE;
+        }
+
+        if (!mCapabilities.layeredBuffers && descriptorInfo.layerCount != 1) {
+            return Error::UNSUPPORTED;
+        }
+
+        if (descriptorInfo.format == static_cast<PixelFormat>(0)) {
+            return Error::BAD_VALUE;
+        }
+
+        const uint64_t validUsageBits = getValidBufferUsageMask();
+        if (descriptorInfo.usage & ~validUsageBits) {
+            ALOGW("buffer descriptor with invalid usage bits 0x%" PRIx64,
+                  descriptorInfo.usage & ~validUsageBits);
+        }
+
+        *outDescriptor = grallocEncodeBufferDescriptor(descriptorInfo);
+
+        return Error::NONE;
+    }
+
+    Error importBuffer(const native_handle_t* rawHandle,
+                       native_handle_t** outBufferHandle) override {
+        native_handle_t* bufferHandle = native_handle_clone(rawHandle);
+        if (!bufferHandle) {
+            return Error::NO_RESOURCES;
+        }
+
+        int32_t error = mDispatch.retain(mDevice, bufferHandle);
+        if (error != GRALLOC1_ERROR_NONE) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+            return toError(error);
+        }
+
+        *outBufferHandle = bufferHandle;
+
+        return Error::NONE;
+    }
+
+    Error freeBuffer(native_handle_t* bufferHandle) override {
+        int32_t error = mDispatch.release(mDevice, bufferHandle);
+        if (error == GRALLOC1_ERROR_NONE && !mCapabilities.releaseImplyDelete) {
+            native_handle_close(bufferHandle);
+            native_handle_delete(bufferHandle);
+        }
+        return toError(error);
+    }
+
+    Error lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+               void** outData) override {
+        const uint64_t consumerUsage =
+            cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+        const auto accessRect = asGralloc1Rect(accessRegion);
+        void* data = nullptr;
+        int32_t error = mDispatch.lock(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+                                       &data, fenceFd.release());
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outData = data;
+        }
+
+        return toError(error);
+    }
+
+    Error lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                    const IMapper::Rect& accessRegion, base::unique_fd fenceFd,
+                    YCbCrLayout* outLayout) override {
+        // prepare flex layout
+        android_flex_layout flex = {};
+        int32_t error = mDispatch.getNumFlexPlanes(mDevice, bufferHandle, &flex.num_planes);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        std::vector<android_flex_plane_t> flexPlanes(flex.num_planes);
+        flex.planes = flexPlanes.data();
+
+        const uint64_t consumerUsage =
+            cpuUsage & ~static_cast<uint64_t>(BufferUsage::CPU_WRITE_MASK);
+        const auto accessRect = asGralloc1Rect(accessRegion);
+        error = mDispatch.lockFlex(mDevice, bufferHandle, cpuUsage, consumerUsage, &accessRect,
+                                   &flex, fenceFd.release());
+        if (error == GRALLOC1_ERROR_NONE && !toYCbCrLayout(flex, outLayout)) {
+            ALOGD("unable to convert android_flex_layout to YCbCrLayout");
+            // undo the lock
+            unlock(bufferHandle, &fenceFd);
+            error = GRALLOC1_ERROR_BAD_HANDLE;
+        }
+
+        return toError(error);
+    }
+
+    Error unlock(const native_handle_t* bufferHandle, base::unique_fd* outFenceFd) override {
+        int fenceFd = -1;
+        int32_t error = mDispatch.unlock(mDevice, bufferHandle, &fenceFd);
+
+        // we always own the fenceFd even when unlock failed
+        outFenceFd->reset(fenceFd);
+        return toError(error);
+    }
+
+   protected:
+    virtual void initCapabilities() {
+        uint32_t count = 0;
+        mDevice->getCapabilities(mDevice, &count, nullptr);
+
+        std::vector<int32_t> capabilities(count);
+        mDevice->getCapabilities(mDevice, &count, capabilities.data());
+        capabilities.resize(count);
+
+        for (auto capability : capabilities) {
+            switch (capability) {
+                case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+                    mCapabilities.layeredBuffers = true;
+                    break;
+                case GRALLOC1_CAPABILITY_RELEASE_IMPLY_DELETE:
+                    mCapabilities.releaseImplyDelete = true;
+                    break;
+            }
+        }
+    }
+
+    template <typename T>
+    bool initDispatch(gralloc1_function_descriptor_t desc, T* outPfn) {
+        auto pfn = mDevice->getFunction(mDevice, desc);
+        if (pfn) {
+            *outPfn = reinterpret_cast<T>(pfn);
+            return true;
+        } else {
+            ALOGE("failed to get gralloc1 function %d", desc);
+            return false;
+        }
+    }
+
+    virtual bool initDispatch() {
+        if (!initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain) ||
+            !initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES, &mDispatch.getNumFlexPlanes) ||
+            !initDispatch(GRALLOC1_FUNCTION_LOCK, &mDispatch.lock) ||
+            !initDispatch(GRALLOC1_FUNCTION_LOCK_FLEX, &mDispatch.lockFlex) ||
+            !initDispatch(GRALLOC1_FUNCTION_UNLOCK, &mDispatch.unlock)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    virtual uint64_t getValidBufferUsageMask() const {
+        return BufferUsage::CPU_READ_MASK | BufferUsage::CPU_WRITE_MASK | BufferUsage::GPU_TEXTURE |
+               BufferUsage::GPU_RENDER_TARGET | BufferUsage::COMPOSER_OVERLAY |
+               BufferUsage::COMPOSER_CLIENT_TARGET | BufferUsage::PROTECTED |
+               BufferUsage::COMPOSER_CURSOR | BufferUsage::VIDEO_ENCODER |
+               BufferUsage::CAMERA_OUTPUT | BufferUsage::CAMERA_INPUT | BufferUsage::RENDERSCRIPT |
+               BufferUsage::VIDEO_DECODER | BufferUsage::SENSOR_DIRECT_DATA |
+               BufferUsage::GPU_DATA_BUFFER | BufferUsage::VENDOR_MASK |
+               BufferUsage::VENDOR_MASK_HI;
+    }
+
+    static Error toError(int32_t error) {
+        switch (error) {
+            case GRALLOC1_ERROR_NONE:
+                return Error::NONE;
+            case GRALLOC1_ERROR_BAD_DESCRIPTOR:
+                return Error::BAD_DESCRIPTOR;
+            case GRALLOC1_ERROR_BAD_HANDLE:
+                return Error::BAD_BUFFER;
+            case GRALLOC1_ERROR_BAD_VALUE:
+                return Error::BAD_VALUE;
+            case GRALLOC1_ERROR_NOT_SHARED:
+                return Error::NONE;  // this is fine
+            case GRALLOC1_ERROR_NO_RESOURCES:
+                return Error::NO_RESOURCES;
+            case GRALLOC1_ERROR_UNDEFINED:
+            case GRALLOC1_ERROR_UNSUPPORTED:
+            default:
+                return Error::UNSUPPORTED;
+        }
+    }
+
+    static bool toYCbCrLayout(const android_flex_layout& flex, YCbCrLayout* outLayout) {
+        // must be YCbCr
+        if (flex.format != FLEX_FORMAT_YCbCr || flex.num_planes < 3) {
+            return false;
+        }
+
+        for (int i = 0; i < 3; i++) {
+            const auto& plane = flex.planes[i];
+            // must have 8-bit depth
+            if (plane.bits_per_component != 8 || plane.bits_used != 8) {
+                return false;
+            }
+
+            if (plane.component == FLEX_COMPONENT_Y) {
+                // Y must not be interleaved
+                if (plane.h_increment != 1) {
+                    return false;
+                }
+            } else {
+                // Cb and Cr can be interleaved
+                if (plane.h_increment != 1 && plane.h_increment != 2) {
+                    return false;
+                }
+            }
+
+            if (!plane.v_increment) {
+                return false;
+            }
+        }
+
+        if (flex.planes[0].component != FLEX_COMPONENT_Y ||
+            flex.planes[1].component != FLEX_COMPONENT_Cb ||
+            flex.planes[2].component != FLEX_COMPONENT_Cr) {
+            return false;
+        }
+
+        const auto& y = flex.planes[0];
+        const auto& cb = flex.planes[1];
+        const auto& cr = flex.planes[2];
+
+        if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
+            return false;
+        }
+
+        outLayout->y = y.top_left;
+        outLayout->cb = cb.top_left;
+        outLayout->cr = cr.top_left;
+        outLayout->yStride = y.v_increment;
+        outLayout->cStride = cb.v_increment;
+        outLayout->chromaStep = cb.h_increment;
+
+        return true;
+    }
+
+    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect) {
+        return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+    }
+
+    gralloc1_device_t* mDevice = nullptr;
+
+    struct {
+        bool layeredBuffers;
+        bool releaseImplyDelete;
+    } mCapabilities = {};
+
+    struct {
+        GRALLOC1_PFN_RETAIN retain;
+        GRALLOC1_PFN_RELEASE release;
+        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+        GRALLOC1_PFN_LOCK lock;
+        GRALLOC1_PFN_LOCK_FLEX lockFlex;
+        GRALLOC1_PFN_UNLOCK unlock;
+    } mDispatch = {};
+};
+
+}  // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
similarity index 84%
rename from graphics/mapper/2.0/default/GrallocBufferDescriptor.h
rename to graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
index 9b5ab04..4c477e1 100644
--- a/graphics/mapper/2.0/default/GrallocBufferDescriptor.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocBufferDescriptor.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
-#define ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
+#pragma once
 
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 
@@ -24,7 +23,7 @@
 namespace graphics {
 namespace mapper {
 namespace V2_0 {
-namespace implementation {
+namespace passthrough {
 
 using android::hardware::graphics::common::V1_0::PixelFormat;
 
@@ -50,9 +49,8 @@
     return descriptor;
 }
 
-inline bool grallocDecodeBufferDescriptor(
-    const BufferDescriptor& descriptor,
-    IMapper::BufferDescriptorInfo* outDescriptorInfo) {
+inline bool grallocDecodeBufferDescriptor(const BufferDescriptor& descriptor,
+                                          IMapper::BufferDescriptorInfo* outDescriptorInfo) {
     if (descriptor.size() != grallocBufferDescriptorSize ||
         descriptor[0] != grallocBufferDescriptorMagicVersion) {
         return false;
@@ -69,11 +67,9 @@
     return true;
 }
 
-}  // namespace implementation
+}  // namespace passthrough
 }  // namespace V2_0
 }  // namespace mapper
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-#endif  // ANDROID_HARDWARE_GRAPHICS_MAPPER_V2_0_GRALLOCBUFFERDESCRIPTOR_H
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
new file mode 100644
index 0000000..e8b1b4b
--- /dev/null
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "GrallocLoader.h included without LOG_TAG"
+#endif
+
+#include <memory>
+#include <mutex>
+#include <unordered_set>
+
+#include <hardware/gralloc.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+#include <mapper-hal/2.0/Mapper.h>
+#include <mapper-passthrough/2.0/Gralloc0Hal.h>
+#include <mapper-passthrough/2.0/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace passthrough {
+
+class GrallocImportedBufferPool {
+   public:
+    static GrallocImportedBufferPool& getInstance() {
+        // GraphicBufferMapper in framework is expected to be valid (and
+        // leaked) during process termination.  We need to make sure IMapper,
+        // and in turn, GrallocImportedBufferPool is valid as well.  Create
+        // imported buffer pool on the heap (and let it leak) for the purpose.
+        // Besides, all IMapper instances must share the same pool.  Make it a
+        // singleton.
+        //
+        // However, there is no way to make sure gralloc0/gralloc1 are valid
+        // during process termination.  Any use of static/global object in
+        // gralloc0/gralloc1 that may be destructed during process termination
+        // is potentially broken.
+        static GrallocImportedBufferPool* singleton = new GrallocImportedBufferPool;
+        return *singleton;
+    }
+
+    void* add(native_handle_t* bufferHandle) {
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.insert(bufferHandle).second ? bufferHandle : nullptr;
+    }
+
+    native_handle_t* remove(void* buffer) {
+        auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
+    }
+
+    const native_handle_t* get(void* buffer) {
+        auto bufferHandle = static_cast<const native_handle_t*>(buffer);
+
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+    }
+
+   private:
+    std::mutex mMutex;
+    std::unordered_set<const native_handle_t*> mBufferHandles;
+};
+
+// Inherit from V2_*::hal::Mapper and override imported buffer management functions
+template <typename T>
+class GrallocMapper : public T {
+   protected:
+    void* addImportedBuffer(native_handle_t* bufferHandle) override {
+        return GrallocImportedBufferPool::getInstance().add(bufferHandle);
+    }
+
+    native_handle_t* removeImportedBuffer(void* buffer) override {
+        return GrallocImportedBufferPool::getInstance().remove(buffer);
+    }
+
+    const native_handle_t* getImportedBuffer(void* buffer) const override {
+        return GrallocImportedBufferPool::getInstance().get(buffer);
+    }
+};
+
+class GrallocLoader {
+   public:
+    static IMapper* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createMapper(std::move(hal));
+    }
+
+    // load the gralloc module
+    static const hw_module_t* loadModule() {
+        const hw_module_t* module;
+        int error = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        if (error) {
+            ALOGE("failed to get gralloc module");
+            return nullptr;
+        }
+
+        return module;
+    }
+
+    // return the major api version of the module
+    static int getModuleMajorApiVersion(const hw_module_t* module) {
+        return (module->module_api_version >> 8) & 0xff;
+    }
+
+    // create a MapperHal instance
+    static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
+        int major = getModuleMajorApiVersion(module);
+        switch (major) {
+            case 1: {
+                auto hal = std::make_unique<Gralloc1Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            case 0: {
+                auto hal = std::make_unique<Gralloc0Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            default:
+                ALOGE("unknown gralloc module major version %d", major);
+                return nullptr;
+        }
+    }
+
+    // create an IAllocator instance
+    static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
+        auto mapper = std::make_unique<GrallocMapper<hal::Mapper>>();
+        return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.0/utils/vts/Android.bp b/graphics/mapper/2.0/utils/vts/Android.bp
new file mode 100644
index 0000000..1aa3185
--- /dev/null
+++ b/graphics/mapper/2.0/utils/vts/Android.bp
@@ -0,0 +1,38 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.mapper@2.0-vts",
+    defaults: ["hidl_defaults"],
+    srcs: ["MapperVts.cpp"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+    shared_libs: [
+        "libutils",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
similarity index 64%
rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
rename to graphics/mapper/2.0/utils/vts/MapperVts.cpp
index 671c4b1..d08ac56 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.cpp
+++ b/graphics/mapper/2.0/utils/vts/MapperVts.cpp
@@ -14,28 +14,26 @@
  * limitations under the License.
  */
 
-#include <VtsHalHidlTargetTestBase.h>
+#include <mapper-vts/2.0/MapperVts.h>
 
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <VtsHalHidlTargetTestBase.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace mapper {
 namespace V2_0 {
-namespace tests {
+namespace vts {
 
-Gralloc::Gralloc() {
-    init();
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName) {
+    init(allocatorServiceName, mapperServiceName);
 }
 
-void Gralloc::init() {
-    mAllocator = ::testing::VtsHalHidlTargetTestBase::getService<IAllocator>(
-        GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>());
+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>(
-        GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>());
+    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";
 }
@@ -50,8 +48,7 @@
 
     for (auto bufferHandle : mImportedBuffers) {
         auto buffer = const_cast<native_handle_t*>(bufferHandle);
-        EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer))
-            << "failed to free buffer " << buffer;
+        EXPECT_EQ(Error::NONE, mMapper->freeBuffer(buffer)) << "failed to free buffer " << buffer;
     }
     mImportedBuffers.clear();
 }
@@ -62,15 +59,13 @@
 
 std::string Gralloc::dumpDebugInfo() {
     std::string debugInfo;
-    mAllocator->dumpDebugInfo(
-        [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+    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());
+    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
     EXPECT_NE(nullptr, bufferHandle);
 
     if (bufferHandle) {
@@ -80,24 +75,22 @@
     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*> 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) {
+        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])));
+                    ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(importBuffer(tmpBuffers[i])));
                 } else {
-                    ASSERT_NO_FATAL_FAILURE(
-                        bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
+                    ASSERT_NO_FATAL_FAILURE(bufferHandles.push_back(cloneBuffer(tmpBuffers[i])));
                 }
             }
 
@@ -113,9 +106,8 @@
     return bufferHandles;
 }
 
-const native_handle_t* Gralloc::allocate(
-    const IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
-    uint32_t* outStride) {
+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;
@@ -133,26 +125,23 @@
     return mMapper;
 }
 
-BufferDescriptor Gralloc::createDescriptor(
-    const IMapper::BufferDescriptorInfo& descriptorInfo) {
+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;
-        });
+    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);
-        });
+    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);
@@ -189,8 +178,7 @@
     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;
+                      ASSERT_EQ(Error::NONE, tmpError) << "failed to lock buffer " << buffer;
                       data = tmpData;
                   });
 
@@ -201,10 +189,8 @@
     return data;
 }
 
-YCbCrLayout Gralloc::lockYCbCr(const native_handle_t* bufferHandle,
-                               uint64_t cpuUsage,
-                               const IMapper::Rect& accessRegion,
-                               int acquireFence) {
+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);
@@ -234,29 +220,25 @@
     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;
+    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;
-                }
+        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;
 }
 
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_0
 }  // namespace mapper
 }  // namespace graphics
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
similarity index 64%
rename from graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
rename to graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
index 9cf60a3..6c2c9a6 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperTestUtils.h
+++ b/graphics/mapper/2.0/utils/vts/include/mapper-vts/2.0/MapperVts.h
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_GRAPHICS_MAPPER_UTILS
-#define VTS_HAL_GRAPHICS_MAPPER_UTILS
+#pragma once
 
+#include <string>
 #include <unordered_set>
+#include <vector>
 
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <utils/StrongPointer.h>
@@ -29,14 +29,15 @@
 namespace graphics {
 namespace mapper {
 namespace V2_0 {
-namespace tests {
+namespace vts {
 
 using android::hardware::graphics::allocator::V2_0::IAllocator;
 
 // A wrapper to IAllocator and IMapper.
 class Gralloc {
    public:
-    Gralloc();
+    Gralloc(const std::string& allocatorServiceName = "default",
+            const std::string& mapperServiceName = "default");
     ~Gralloc();
 
     // IAllocator methods
@@ -49,19 +50,16 @@
     // 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);
+    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);
+    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
     const native_handle_t* importBuffer(const hidl_handle& rawHandle);
     void freeBuffer(const native_handle_t* bufferHandle);
@@ -71,13 +69,12 @@
     // 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);
+    YCbCrLayout lockYCbCr(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                          const IMapper::Rect& accessRegion, int acquireFence);
     int unlock(const native_handle_t* bufferHandle);
 
    private:
-    void init();
+    void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
     const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
 
     sp<IAllocator> mAllocator;
@@ -89,26 +86,9 @@
     std::unordered_set<const native_handle_t*> mImportedBuffers;
 };
 
-// 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>();
-    }
-};
-
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_0
 }  // namespace mapper
 }  // namespace graphics
 }  // namespace hardware
 }  // namespace android
-
-#endif  // VTS_HAL_GRAPHICS_MAPPER_UTILS
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index ac6cb47..969317a 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -14,39 +14,14 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "libVtsHalGraphicsMapperTestUtils",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalGraphicsMapperTestUtils.cpp"],
-    shared_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.mapper@2.0",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-    ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ],
-    export_include_dirs: ["."],
-}
-
 cc_test {
     name: "VtsHalGraphicsMapperV2_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libsync",
-    ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.common@1.0",
-        "libVtsHalGraphicsMapperTestUtils",
-        "libnativehelper",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.0-vts",
     ],
 }
diff --git a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
index 1f94898..aa9beff 100644
--- a/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
+++ b/graphics/mapper/2.0/vts/functional/VtsHalGraphicsMapperV2_0TargetTest.cpp
@@ -18,37 +18,54 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
-#include <sync/sync.h>
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <mapper-vts/2.0/MapperVts.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace mapper {
 namespace V2_0 {
-namespace tests {
+namespace vts {
 namespace {
 
 using android::hardware::graphics::common::V1_0::BufferUsage;
 using android::hardware::graphics::common::V1_0::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>());
+   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);
-  }
+        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 {}
+    void TearDown() override {}
 
-  std::unique_ptr<Gralloc> mGralloc;
-  IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
+    std::unique_ptr<Gralloc> mGralloc;
+    IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
 };
 
 /**
@@ -63,18 +80,16 @@
  */
 TEST_F(GraphicsMapperHidlTest, AllocatorAllocate) {
     BufferDescriptor descriptor;
-    ASSERT_NO_FATAL_FAILURE(
-        descriptor = mGralloc->createDescriptor(mDummyDescriptorInfo));
+    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));
+        ASSERT_NO_FATAL_FAILURE(bufferHandles =
+                                    mGralloc->allocate(descriptor, count, false, &stride));
 
         if (count >= 1) {
-            EXPECT_LE(mDummyDescriptorInfo.width, stride)
-                << "invalid buffer stride";
+            EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
         }
 
         for (auto bufferHandle : bufferHandles) {
@@ -89,10 +104,10 @@
 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);
-        });
+    mGralloc->getAllocator()->allocate(descriptor, 1,
+                                       [&](const auto& tmpError, const auto&, const auto&) {
+                                           EXPECT_EQ(Error::BAD_DESCRIPTOR, tmpError);
+                                       });
 }
 
 /**
@@ -122,11 +137,9 @@
 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";
-        });
+    mGralloc->getMapper()->createDescriptor(info, [&](const auto& tmpError, const auto&) {
+        EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
+    });
 }
 
 /**
@@ -134,8 +147,7 @@
  */
 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferBasic) {
     const native_handle_t* bufferHandle;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle =
-                                mGralloc->allocate(mDummyDescriptorInfo, true));
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
     ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
 }
 
@@ -144,16 +156,13 @@
  */
 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferClone) {
     const native_handle_t* clonedBufferHandle;
-    ASSERT_NO_FATAL_FAILURE(
-        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    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(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]));
 
@@ -165,19 +174,20 @@
  */
 TEST_F(GraphicsMapperHidlTest, ImportFreeBufferSingleton) {
     const native_handle_t* rawHandle;
-    ASSERT_NO_FATAL_FAILURE(
-        rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    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);
-        });
+    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>());
+    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);
 
@@ -203,15 +213,13 @@
  */
 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";
-        });
+    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&) {
+    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";
     });
@@ -224,8 +232,7 @@
 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";
+    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);
@@ -234,8 +241,7 @@
     native_handle_delete(invalidHandle);
 
     const native_handle_t* clonedBufferHandle;
-    ASSERT_NO_FATAL_FAILURE(
-        clonedBufferHandle = mGralloc->allocate(mDummyDescriptorInfo, false));
+    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";
@@ -251,16 +257,15 @@
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle =
-                                mGralloc->allocate(info, true, &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)));
+    ASSERT_NO_FATAL_FAILURE(
+        data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
 
     // RGBA_8888
     size_t strideInBytes = stride * 4;
@@ -274,8 +279,8 @@
     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)));
+    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]);
@@ -299,16 +304,14 @@
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle =
-                                mGralloc->allocate(info, true, &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));
+    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);
@@ -328,8 +331,7 @@
     ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
 
     // lock again for reading
-    ASSERT_NO_FATAL_FAILURE(
-        layout = mGralloc->lockYCbCr(bufferHandle, info.usage, region, fence));
+    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);
@@ -357,25 +359,21 @@
  */
 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";
-        });
+    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";
-        });
+    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&) {
+    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";
     });
@@ -395,7 +393,7 @@
 }
 
 }  // namespace
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_0
 }  // namespace mapper
 }  // namespace graphics
@@ -403,7 +401,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+    using android::hardware::graphics::mapper::V2_0::vts::GraphicsMapperHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/graphics/mapper/2.1/default/Android.bp b/graphics/mapper/2.1/default/Android.bp
new file mode 100644
index 0000000..aa204a0
--- /dev/null
+++ b/graphics/mapper/2.1/default/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@2.0-impl-2.1",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["passthrough.cpp"],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.1-passthrough",
+    ],
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+}
diff --git a/graphics/mapper/2.1/default/OWNERS b/graphics/mapper/2.1/default/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.1/default/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.1/default/passthrough.cpp b/graphics/mapper/2.1/default/passthrough.cpp
new file mode 100644
index 0000000..c7f0cf5
--- /dev/null
+++ b/graphics/mapper/2.1/default/passthrough.cpp
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-passthrough/2.1/GrallocLoader.h>
+
+using android::hardware::graphics::mapper::V2_1::IMapper;
+using android::hardware::graphics::mapper::V2_1::passthrough::GrallocLoader;
+
+extern "C" IMapper* HIDL_FETCH_IMapper(const char* /*name*/) {
+    return GrallocLoader::load();
+}
diff --git a/graphics/mapper/2.1/utils/OWNERS b/graphics/mapper/2.1/utils/OWNERS
new file mode 100644
index 0000000..3aa5fa1
--- /dev/null
+++ b/graphics/mapper/2.1/utils/OWNERS
@@ -0,0 +1,4 @@
+# Graphics team
+jessehall@google.com
+olv@google.com
+stoza@google.com
diff --git a/graphics/mapper/2.1/utils/hal/Android.bp b/graphics/mapper/2.1/utils/hal/Android.bp
new file mode 100644
index 0000000..2a4cc6e
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.1-hal",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.1",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.mapper@2.1",
+    ],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.mapper@2.0-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
new file mode 100644
index 0000000..038f572
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/Mapper.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "Mapper.h included without LOG_TAG"
+#endif
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-hal/2.0/Mapper.h>
+#include <mapper-hal/2.1/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace hal {
+
+namespace detail {
+
+// MapperImpl implements V2_*::IMapper on top of V2_*::hal::MapperHal
+template <typename Interface, typename Hal>
+class MapperImpl : public V2_0::hal::detail::MapperImpl<Interface, Hal> {
+   public:
+    // IMapper 2.1 interface
+    Return<Error> validateBufferSize(void* buffer,
+                                     const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                     uint32_t stride) {
+        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        if (!bufferHandle) {
+            return Error::BAD_BUFFER;
+        }
+
+        return mHal->validateBufferSize(bufferHandle, descriptorInfo, stride);
+    }
+
+    Return<void> getTransportSize(void* buffer, IMapper::getTransportSize_cb hidl_cb) {
+        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        if (!bufferHandle) {
+            hidl_cb(Error::BAD_BUFFER, 0, 0);
+            return Void();
+        }
+
+        uint32_t numFds = 0;
+        uint32_t numInts = 0;
+        Error error = mHal->getTransportSize(bufferHandle, &numFds, &numInts);
+        hidl_cb(error, numFds, numInts);
+        return Void();
+    }
+
+    Return<void> createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                      IMapper::createDescriptor_2_1_cb hidl_cb) override {
+        BufferDescriptor descriptor;
+        Error error = mHal->createDescriptor_2_1(descriptorInfo, &descriptor);
+        hidl_cb(error, descriptor);
+        return Void();
+    }
+
+   private:
+    using BaseType2_0 = V2_0::hal::detail::MapperImpl<Interface, Hal>;
+    using BaseType2_0::getImportedBuffer;
+    using BaseType2_0::mHal;
+};
+
+}  // namespace detail
+
+using Mapper = detail::MapperImpl<IMapper, MapperHal>;
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h
new file mode 100644
index 0000000..e488fab
--- /dev/null
+++ b/graphics/mapper/2.1/utils/hal/include/mapper-hal/2.1/MapperHal.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-hal/2.0/MapperHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace hal {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+class MapperHal : public V2_0::hal::MapperHal {
+   public:
+    virtual ~MapperHal() = default;
+
+    // superceded by createDescriptor_2_1
+    Error createDescriptor(const V2_0::IMapper::BufferDescriptorInfo& descriptorInfo,
+                           BufferDescriptor* outDescriptor) override {
+        return createDescriptor_2_1(
+            IMapper::BufferDescriptorInfo{
+                descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+                static_cast<common::V1_1::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+            },
+            outDescriptor);
+    }
+
+    // validate the buffer can be safely accessed with the specified
+    // descriptorInfo and stride
+    virtual Error validateBufferSize(const native_handle_t* bufferHandle,
+                                     const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                     uint32_t stride) = 0;
+
+    // get the transport size of a buffer handle.  It can be smaller than or
+    // equal to the size of the buffer handle.
+    virtual Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                                   uint32_t* outNumInts) = 0;
+
+    // create a BufferDescriptor
+    virtual Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                       BufferDescriptor* outDescriptor) = 0;
+};
+
+}  // namespace hal
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/Android.bp b/graphics/mapper/2.1/utils/passthrough/Android.bp
new file mode 100644
index 0000000..6946a53
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_library_headers {
+    name: "android.hardware.graphics.mapper@2.1-passthrough",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.graphics.mapper@2.1",
+        "libhardware",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.graphics.mapper@2.1",
+        "libhardware",
+    ],
+    header_libs: [
+        "android.hardware.graphics.mapper@2.0-passthrough",
+        "android.hardware.graphics.mapper@2.1-hal",
+    ],
+    export_header_lib_headers: [
+        "android.hardware.graphics.mapper@2.0-passthrough",
+        "android.hardware.graphics.mapper@2.1-hal",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
new file mode 100644
index 0000000..b704fdb
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/Gralloc0Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+namespace detail {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+// Gralloc0HalImpl implements V2_*::hal::MapperHal on top of gralloc0
+template <typename Hal>
+class Gralloc0HalImpl : public V2_0::passthrough::detail::Gralloc0HalImpl<Hal> {
+   public:
+    Error validateBufferSize(const native_handle_t* /*bufferHandle*/,
+                             const IMapper::BufferDescriptorInfo& /*descriptorInfo*/,
+                             uint32_t /*stride*/) override {
+        // need a gralloc0 extension to really validate
+        return Error::NONE;
+    }
+
+    Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                           uint32_t* outNumInts) override {
+        // need a gralloc0 extension to get the transport size
+        *outNumFds = bufferHandle->numFds;
+        *outNumInts = bufferHandle->numInts;
+        return Error::NONE;
+    }
+
+    Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                               BufferDescriptor* outDescriptor) override {
+        return createDescriptor(
+            V2_0::IMapper::BufferDescriptorInfo{
+                descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+                static_cast<common::V1_0::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+            },
+            outDescriptor);
+    }
+
+   private:
+    using BaseType2_0 = V2_0::passthrough::detail::Gralloc0HalImpl<Hal>;
+    using BaseType2_0::createDescriptor;
+};
+
+}  // namespace detail
+
+using Gralloc0Hal = detail::Gralloc0HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h
new file mode 100644
index 0000000..8b695e4
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc1Hal.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <hardware/gralloc1.h>
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+using V2_0::BufferDescriptor;
+using V2_0::Error;
+
+namespace detail {
+
+// Gralloc1HalImpl implements V2_*::hal::MapperHal on top of gralloc1
+template <typename Hal>
+class Gralloc1HalImpl : public V2_0::passthrough::detail::Gralloc1HalImpl<Hal> {
+   public:
+    Error validateBufferSize(const native_handle_t* bufferHandle,
+                             const IMapper::BufferDescriptorInfo& descriptorInfo,
+                             uint32_t stride) override {
+        uint32_t bufferWidth;
+        uint32_t bufferHeight;
+        uint32_t bufferLayerCount;
+        int32_t bufferFormat;
+        uint64_t bufferProducerUsage;
+        uint64_t bufferConsumerUsage;
+        uint32_t bufferStride;
+
+        int32_t error = mDispatch.getDimensions(mDevice, bufferHandle, &bufferWidth, &bufferHeight);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        error = mDispatch.getLayerCount(mDevice, bufferHandle, &bufferLayerCount);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        error = mDispatch.getFormat(mDevice, bufferHandle, &bufferFormat);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        error = mDispatch.getProducerUsage(mDevice, bufferHandle, &bufferProducerUsage);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        error = mDispatch.getConsumerUsage(mDevice, bufferHandle, &bufferConsumerUsage);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+        error = mDispatch.getStride(mDevice, bufferHandle, &bufferStride);
+        if (error != GRALLOC1_ERROR_NONE) {
+            return toError(error);
+        }
+
+        // TODO format? usage? width > stride?
+        // need a gralloc1 extension to really validate
+        (void)bufferFormat;
+        (void)bufferProducerUsage;
+        (void)bufferConsumerUsage;
+
+        if (descriptorInfo.width > bufferWidth || descriptorInfo.height > bufferHeight ||
+            descriptorInfo.layerCount > bufferLayerCount || stride > bufferStride) {
+            return Error::BAD_VALUE;
+        }
+
+        return Error::NONE;
+    }
+
+    Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
+                           uint32_t* outNumInts) override {
+        // need a gralloc1 extension to get the transport size
+        *outNumFds = bufferHandle->numFds;
+        *outNumInts = bufferHandle->numInts;
+        return Error::NONE;
+    }
+
+    Error createDescriptor_2_1(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                               BufferDescriptor* outDescriptor) override {
+        return createDescriptor(
+            V2_0::IMapper::BufferDescriptorInfo{
+                descriptorInfo.width, descriptorInfo.height, descriptorInfo.layerCount,
+                static_cast<common::V1_0::PixelFormat>(descriptorInfo.format), descriptorInfo.usage,
+            },
+            outDescriptor);
+    }
+
+   protected:
+    bool initDispatch() override {
+        if (!BaseType2_0::initDispatch()) {
+            return false;
+        }
+
+        if (!initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT, &mDispatch.getLayerCount) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE, &mDispatch.getProducerUsage) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE, &mDispatch.getConsumerUsage) ||
+            !initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    struct {
+        GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
+        GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
+        GRALLOC1_PFN_GET_FORMAT getFormat;
+        GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
+        GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
+        GRALLOC1_PFN_GET_STRIDE getStride;
+    } mDispatch = {};
+
+   private:
+    using BaseType2_0 = V2_0::passthrough::detail::Gralloc1HalImpl<Hal>;
+    using BaseType2_0::createDescriptor;
+    using BaseType2_0::initDispatch;
+    using BaseType2_0::mDevice;
+    using BaseType2_0::toError;
+};
+
+}  // namespace detail
+
+using Gralloc1Hal = detail::Gralloc1HalImpl<hal::MapperHal>;
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h
new file mode 100644
index 0000000..f2c67db
--- /dev/null
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/GrallocLoader.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <log/log.h>
+#include <mapper-hal/2.1/Mapper.h>
+#include <mapper-hal/2.1/MapperHal.h>
+#include <mapper-passthrough/2.0/GrallocLoader.h>
+#include <mapper-passthrough/2.1/Gralloc0Hal.h>
+#include <mapper-passthrough/2.1/Gralloc1Hal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace passthrough {
+
+class GrallocLoader : public V2_0::passthrough::GrallocLoader {
+   public:
+    static IMapper* load() {
+        const hw_module_t* module = loadModule();
+        if (!module) {
+            return nullptr;
+        }
+        auto hal = createHal(module);
+        if (!hal) {
+            return nullptr;
+        }
+        return createMapper(std::move(hal));
+    }
+
+    // create a MapperHal instance
+    static std::unique_ptr<hal::MapperHal> createHal(const hw_module_t* module) {
+        int major = getModuleMajorApiVersion(module);
+        switch (major) {
+            case 1: {
+                auto hal = std::make_unique<Gralloc1Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            case 0: {
+                auto hal = std::make_unique<Gralloc0Hal>();
+                return hal->initWithModule(module) ? std::move(hal) : nullptr;
+            }
+            default:
+                ALOGE("unknown gralloc module major version %d", major);
+                return nullptr;
+        }
+    }
+
+    // create an IAllocator instance
+    static IMapper* createMapper(std::unique_ptr<hal::MapperHal> hal) {
+        auto mapper = std::make_unique<V2_0::passthrough::GrallocMapper<hal::Mapper>>();
+        return mapper->init(std::move(hal)) ? mapper.release() : nullptr;
+    }
+};
+
+}  // namespace passthrough
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/vts/Android.bp b/graphics/mapper/2.1/utils/vts/Android.bp
new file mode 100644
index 0000000..ca02aad
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/Android.bp
@@ -0,0 +1,39 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.graphics.mapper@2.1-vts",
+    defaults: ["hidl_defaults"],
+    srcs: ["MapperVts.cpp"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@2.1",
+    ],
+    export_static_lib_headers: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@2.1",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/mapper/2.1/utils/vts/MapperVts.cpp b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
new file mode 100644
index 0000000..0aaa926
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/MapperVts.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mapper-vts/2.1/MapperVts.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace vts {
+
+using V2_0::Error;
+
+// abuse VTS to check binary compatibility between BufferDescriptorInfos
+using OldBufferDescriptorInfo =
+    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
+static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
+                  offsetof(OldBufferDescriptorInfo, width) ==
+                      offsetof(IMapper::BufferDescriptorInfo, width) &&
+                  offsetof(OldBufferDescriptorInfo, height) ==
+                      offsetof(IMapper::BufferDescriptorInfo, height) &&
+                  offsetof(OldBufferDescriptorInfo, layerCount) ==
+                      offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
+                  offsetof(OldBufferDescriptorInfo, format) ==
+                      offsetof(IMapper::BufferDescriptorInfo, format) &&
+                  offsetof(OldBufferDescriptorInfo, usage) ==
+                      offsetof(IMapper::BufferDescriptorInfo, usage),
+              "");
+
+Gralloc::Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName)
+    : V2_0::vts::Gralloc(allocatorServiceName, mapperServiceName) {
+    if (::testing::Test::HasFatalFailure()) {
+        return;
+    }
+    init();
+}
+
+void Gralloc::init() {
+    mMapperV2_1 = IMapper::castFrom(V2_0::vts::Gralloc::getMapper());
+    ASSERT_NE(nullptr, mMapperV2_1.get()) << "failed to get mapper 2.1 service";
+}
+
+sp<IMapper> Gralloc::getMapper() const {
+    return mMapperV2_1;
+}
+
+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 = mMapperV2_1->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;
+    mMapperV2_1->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;
+        });
+}
+
+BufferDescriptor Gralloc::createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+    BufferDescriptor descriptor;
+    mMapperV2_1->createDescriptor_2_1(
+        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::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                         bool import, uint32_t* outStride) {
+    BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
+
+    auto buffers = V2_0::vts::Gralloc::allocate(descriptor, 1, import, outStride);
+    if (::testing::Test::HasFatalFailure()) {
+        return nullptr;
+    }
+
+    return buffers[0];
+}
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
new file mode 100644
index 0000000..b7fa751
--- /dev/null
+++ b/graphics/mapper/2.1/utils/vts/include/mapper-vts/2.1/MapperVts.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <mapper-vts/2.0/MapperVts.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace vts {
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using V2_0::BufferDescriptor;
+
+// A wrapper to IAllocator and IMapper.
+class Gralloc : public V2_0::vts::Gralloc {
+   public:
+    Gralloc(const std::string& allocatorServiceName, const std::string& mapperServiceName);
+
+    sp<IMapper> getMapper() const;
+
+    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);
+
+    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
+
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import = true, uint32_t* outStride = nullptr);
+
+   protected:
+    void init();
+
+    sp<IMapper> mMapperV2_1;
+};
+
+}  // namespace vts
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp
index 578d298..ac67af8 100644
--- a/graphics/mapper/2.1/vts/functional/Android.bp
+++ b/graphics/mapper/2.1/vts/functional/Android.bp
@@ -18,15 +18,12 @@
     name: "VtsHalGraphicsMapperV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV2_1TargetTest.cpp"],
-    shared_libs: [
-        "libsync",
-    ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.1",
-        "libVtsHalGraphicsMapperTestUtils",
-        "libnativehelper",
+        "android.hardware.graphics.mapper@2.0-vts",
+        "android.hardware.graphics.mapper@2.1-vts",
     ],
 }
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 88b96ae..5e7cf93 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -19,115 +19,43 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
-#include <sync/sync.h>
-#include "VtsHalGraphicsMapperTestUtils.h"
+#include <mapper-vts/2.1/MapperVts.h>
 
 namespace android {
 namespace hardware {
 namespace graphics {
 namespace mapper {
 namespace V2_1 {
-namespace tests {
+namespace vts {
 namespace {
 
-using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-using android::hardware::graphics::mapper::V2_0::Error;
-
+using android::hardware::graphics::allocator::V2_0::IAllocator;
 using android::hardware::graphics::common::V1_1::BufferUsage;
 using android::hardware::graphics::common::V1_1::PixelFormat;
+using V2_0::Error;
 
-// abuse VTS to check binary compatibility between BufferDescriptorInfos
-using OldBufferDescriptorInfo =
-    android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
-static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
-                  offsetof(OldBufferDescriptorInfo, width) ==
-                      offsetof(IMapper::BufferDescriptorInfo, width) &&
-                  offsetof(OldBufferDescriptorInfo, height) ==
-                      offsetof(IMapper::BufferDescriptorInfo, height) &&
-                  offsetof(OldBufferDescriptorInfo, layerCount) ==
-                      offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
-                  offsetof(OldBufferDescriptorInfo, format) ==
-                      offsetof(IMapper::BufferDescriptorInfo, format) &&
-                  offsetof(OldBufferDescriptorInfo, usage) ==
-                      offsetof(IMapper::BufferDescriptorInfo, usage),
-              "");
-
-class Gralloc : public V2_0::tests::Gralloc {
+// Test environment for graphics.mapper.
+class GraphicsMapperHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
-    Gralloc() : V2_0::tests::Gralloc() {
-        if (::testing::Test::HasFatalFailure()) {
-            return;
-        }
-
-        init();
+    // get the test environment singleton
+    static GraphicsMapperHidlEnvironment* Instance() {
+        static GraphicsMapperHidlEnvironment* instance = new GraphicsMapperHidlEnvironment;
+        return instance;
     }
 
-    sp<IMapper> getMapper() const { return mMapper; }
-
-    bool 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;
+    virtual void registerTestServices() override {
+        registerTestService<IAllocator>();
+        registerTestService<IMapper>();
     }
-
-    void getTransportSize(const native_handle_t* bufferHandle, uint32_t* numFds,
-                          uint32_t* numInts) {
-        auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-        *numFds = 0;
-        *numInts = 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;
-
-            *numFds = tmpNumFds;
-            *numInts = tmpNumInts;
-        });
-    }
-
-    BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
-        BufferDescriptor descriptor;
-        mMapper->createDescriptor_2_1(
-            descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
-                ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
-                descriptor = tmpDescriptor;
-            });
-
-        return descriptor;
-    }
-
-    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                    bool import, uint32_t* outStride = nullptr) {
-        BufferDescriptor descriptor = createDescriptor(descriptorInfo);
-        if (::testing::Test::HasFatalFailure()) {
-            return nullptr;
-        }
-
-        auto buffers = V2_0::tests::Gralloc::allocate(descriptor, 1, import, outStride);
-        if (::testing::Test::HasFatalFailure()) {
-            return nullptr;
-        }
-
-        return buffers[0];
-    }
-
-   private:
-    void init() {
-        mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper());
-        ASSERT_NE(nullptr, mMapper.get()) << "failed to find IMapper 2.1";
-    }
-
-    sp<IMapper> mMapper;
 };
 
 class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    protected:
     void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+        ASSERT_NO_FATAL_FAILURE(
+            mGralloc = std::make_unique<Gralloc>(
+                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IAllocator>(),
+                GraphicsMapperHidlEnvironment::Instance()->getServiceName<IMapper>()));
 
         mDummyDescriptorInfo.width = 64;
         mDummyDescriptorInfo.height = 64;
@@ -291,7 +219,7 @@
 }
 
 }  // namespace
-}  // namespace tests
+}  // namespace vts
 }  // namespace V2_1
 }  // namespace mapper
 }  // namespace graphics
@@ -299,7 +227,7 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-    using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+    using android::hardware::graphics::mapper::V2_1::vts::GraphicsMapperHidlEnvironment;
     ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
     ::testing::InitGoogleTest(&argc, argv);
     GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
diff --git a/health/2.0/README b/health/2.0/README
index a0a5f08..49b2b1e 100644
--- a/health/2.0/README
+++ b/health/2.0/README
@@ -96,4 +96,4 @@
 
 # device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
 # Add device specific permissions to hal_health_default domain, especially
-# if Step 6.2 or Step 7.2 is done.
+# if Step 6.1 or Step 7.2 is done.
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
new file mode 100644
index 0000000..986da8a
--- /dev/null
+++ b/media/bufferpool/1.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.media.bufferpool@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IAccessor.hal",
+        "IClientManager.hal",
+        "IConnection.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Buffer",
+        "BufferStatus",
+        "BufferStatusMessage",
+        "ResultStatus",
+    ],
+    gen_java: false,
+}
+
diff --git a/media/bufferpool/1.0/IAccessor.hal b/media/bufferpool/1.0/IAccessor.hal
new file mode 100644
index 0000000..5b5aec0
--- /dev/null
+++ b/media/bufferpool/1.0/IAccessor.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.media.bufferpool@1.0;
+
+import IConnection;
+/**
+ * IAccessor creates IConnection which is used from IClientManager in order to
+ * use functionality of the specified buffer pool.
+ */
+interface IAccessor {
+
+    /**
+     * Registers a new client and creates IConnection to the buffer pool for
+     * the client. IConnection and FMQ are used by IClientManager in order to
+     * communicate with the buffer pool. Via FMQ IClientManager sends
+     * BufferStatusMesage(s) to the buffer pool.
+     *
+     * FMQ is used to send buffer ownership status changes to a buffer pool
+     * from a buffer pool client. A buffer pool synchronizes FMQ messages when
+     * there is a hidl request from the clients. Every client has its own
+     * connection and FMQ to communicate with the buffer pool. So sending an
+     * FMQ message on behalf of other clients is not possible.
+     *
+     * FMQ messages are sent when a buffer is acquired or released. Also, FMQ
+     * messages are sent when a buffer is transferred from a client to another
+     * client. FMQ has its own ID from a buffer pool. A client is specified
+     * with the ID.
+     *
+     * To transfer a buffer, a sender must send an FMQ message. The message
+     * must include a receiver's ID and a transaction ID. A receiver must send
+     * the transaction ID to fetch a buffer from a buffer pool. Since the
+     * sender already registered the receiver via an FMQ message, The buffer
+     * pool must verify the receiver with the transaction ID. In order to
+     * prevent faking a receiver, a connection to a buffer pool from client is
+     * made and kept private. Also part of transaction ID is a sender ID in
+     * order to prevent fake transactions from other clients. This must be
+     * verified with an FMQ message from a buffer pool.
+     *
+     * @return status The status of the call.
+     *     OK               - A connection is made successfully.
+     *     NO_MEMORY        - Memory allocation failure occurred.
+     *     ALREADY_EXISTS   - A connection was already made.
+     *     CRITICAL_ERROR   - Other errors.
+     * @return connection The IConnection have interfaces
+     *     to get shared buffers from the buffer pool.
+     * @return connectionId Id of IConnection. The Id identifies
+     *     sender and receiver in FMQ messages during buffer transfer.
+     * @return mqDesc FMQ descriptor. The descriptor can be used to
+     *     send/receive FMQ messages.
+     */
+    connect()
+        generates (ResultStatus status, IConnection connection,
+                   int64_t connectionId, fmq_sync<BufferStatusMessage> mqDesc);
+};
diff --git a/media/bufferpool/1.0/IClientManager.hal b/media/bufferpool/1.0/IClientManager.hal
new file mode 100644
index 0000000..e1e8f95
--- /dev/null
+++ b/media/bufferpool/1.0/IClientManager.hal
@@ -0,0 +1,47 @@
+/*
+ * 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.media.bufferpool@1.0;
+
+import IAccessor;
+/**
+ * IClientManager manages IConnection(s) inside a process. A locally
+ * created IConnection represents a communication node(receiver) with the
+ * specified buffer pool(IAccessor).
+ * IConnection(s) are not exposed to other processes(IClientManager).
+ * IClientManager instance must be unique within a process.
+ */
+interface IClientManager {
+
+    /**
+     * Sets up a buffer receiving communication node for the specified
+     * buffer pool. A manager must create a IConnection to the buffer
+     * pool if it does not already have a connection.
+     *
+     * @param bufferPool a buffer pool which is specified with the IAccessor.
+     *     The specified buffer pool is the owner of received buffers.
+     * @return status The status of the call.
+     *     OK               - A sender was set successfully.
+     *     NO_MEMORY        - Memory allocation failure occurred.
+     *     ALREADY_EXISTS   - A sender was registered already.
+     *     CRITICAL_ERROR   - Other errors.
+     * @return connectionId the Id of the communication node to the buffer pool.
+     *     This id is used in FMQ to notify IAccessor that a buffer has been
+     *     sent to that connection during transfers.
+     */
+    registerSender(IAccessor bufferPool) generates
+        (ResultStatus status, int64_t connectionId);
+};
diff --git a/media/bufferpool/1.0/IConnection.hal b/media/bufferpool/1.0/IConnection.hal
new file mode 100644
index 0000000..e284db2
--- /dev/null
+++ b/media/bufferpool/1.0/IConnection.hal
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool@1.0;
+
+/**
+ * A connection to a buffer pool which handles requests from a buffer pool
+ * client. The connection must be made in order to receive buffers from
+ * other buffer pool clients.
+ */
+interface IConnection {
+
+    /**
+     * Retrieves a buffer using bufferId. The method must be called from
+     * receiving side of buffer during transferring only when the specified
+     * buffer is neither cached nor used. This fails if the specified
+     * transaction is not valid.
+     *
+     * @param transactionId Unique transaction id for buffer transferring.
+     * @param bufferId Id of the buffer to be fetched.
+     * @return status The status of the call.
+     *     OK               - A buffer was fetched successfully.
+     *     NO_MEMORY        - Memory allocation failure occurred.
+     *     NOT_FOUND        - A buffer was not found due to invalidation.
+     *     CRITICAL_ERROR   - Other errors.
+     * @return buffer The actual buffer which is specified with bufferId.
+     */
+    fetch(uint64_t transactionId, uint32_t bufferId) generates
+        (ResultStatus status, Buffer buffer);
+};
diff --git a/media/bufferpool/1.0/README.md b/media/bufferpool/1.0/README.md
new file mode 100644
index 0000000..ed985d8
--- /dev/null
+++ b/media/bufferpool/1.0/README.md
@@ -0,0 +1,54 @@
+1. Overview
+
+A buffer pool enables processes to transfer buffers asynchronously.
+Without a buffer pool, a process calls a synchronous method of the other
+process and waits until the call finishes transferring a buffer. This adds
+unwanted latency due to context switching. With help from a buffer pool, a
+process can pass buffers asynchronously and reduce context switching latency.
+
+Passing an interface and a handle adds extra latency also. To mitigate the
+latency, passing IDs with local cache is used. For security concerns about
+rogue clients, FMQ is used to communicate between a buffer pool and a client
+process. FMQ is used to send buffer ownership change status from a client
+process to a buffer pool. Except FMQ, a buffer pool does not use any shared
+memory.
+
+2. FMQ
+
+FMQ is used to send buffer ownership status changes to a buffer pool from a
+buffer pool client. A buffer pool synchronizes FMQ messages when there is a
+hidl request from the clients. Every client has its own connection and FMQ
+to communicate with the buffer pool. So sending an FMQ message on behalf of
+other clients is not possible.
+
+FMQ messages are sent when a buffer is acquired or released. Also, FMQ messages
+are sent when a buffer is transferred from a client to another client. FMQ has
+its own ID from a buffer pool. A client is specified with the ID.
+
+To transfer a buffer, a sender must send an FMQ message. The message must
+include a receiver's ID and a transaction ID. A receiver must send the
+transaction ID to fetch a buffer from a buffer pool. Since the sender already
+registered the receiver via an FMQ message, The buffer pool must verify the
+receiver with the transaction ID. In order to prevent faking a receiver, a
+connection to a buffer pool from client is made and kept privately. Also part of
+transaction ID is a sender ID in order to prevent fake transactions from other
+clients. This must be verified with an FMQ message from a buffer pool.
+
+FMQ messages are defined in BufferStatus and BufferStatusMessage of 'types.hal'.
+
+3. Interfaces
+
+IConnection
+A connection to a buffer pool from a buffer pool client. The connection
+provides the functionalities to share buffers between buffer pool clients.
+The connection must be unique for each client.
+
+IAccessor
+An accessor to a buffer pool which makes a connection to the buffer pool.
+IAccesssor#connect creates an IConnection.
+
+IClientManager
+A manager of buffer pool clients and clients' connections to buffer pools. It
+sets up a process to be a receiver of buffers from a buffer pool. The manager
+is unique in a process.
+
diff --git a/media/bufferpool/1.0/types.hal b/media/bufferpool/1.0/types.hal
new file mode 100644
index 0000000..d8ab597
--- /dev/null
+++ b/media/bufferpool/1.0/types.hal
@@ -0,0 +1,93 @@
+/*
+ * 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.media.bufferpool@1.0;
+
+enum ResultStatus : int32_t {
+    OK                  = 0,
+
+    NO_MEMORY           = 1,
+    ALREADY_EXISTS      = 2,
+    NOT_FOUND           = 3,
+    CRITICAL_ERROR      = 4,
+};
+
+/**
+ * Generic buffer for fast recycling for media/stagefright.
+ *
+ * During media pipeline buffer references are created, shared and
+ * destroyed frequently. The underlying buffers are allocated on demand
+ * by a buffer pool, and are recycled to the buffer pool when they are
+ * no longer referenced by the clients.
+ *
+ * E.g. ion or gralloc buffer
+ */
+struct Buffer {
+    uint32_t id;
+    handle buffer;
+};
+
+/**
+ * Buffer ownership status for the specified client.
+ * Buffer transfer status for the specified buffer transafer transaction.
+ * BufferStatus is posted along with BufferStatusMessage from a client to
+ * the buffer pool for synchronization after status change.
+ */
+enum BufferStatus : int32_t {
+    /** No longer used by the specified client. */
+    NOT_USED            = 0,
+    /** Buffer is acquired by the specified client. */
+    USED                = 1,
+    /** Buffer is sent by the specified client. */
+    TRANSFER_TO         = 2,
+    /** Buffer transfer is acked by the receiver client. */
+    TRANSFER_FROM       = 3,
+    /** Buffer transfer is timed out by receiver client. */
+    TRANSFER_TIMEOUT    = 4,
+    /** Buffer transfer is not acked by the receiver. */
+    TRANSFER_LOST       = 5,
+    /** Buffer fetch request from the client. */
+    TRANSFER_FETCH      = 6,
+    /** Buffer transaction succeeded. */
+    TRANSFER_OK         = 7,
+    /** Buffer transaction failure. */
+    TRANSFER_ERROR      = 8,
+};
+
+/**
+ * Buffer ownership status change message. This message is
+ * sent via fmq to the buffer pool from client processes.
+ */
+struct BufferStatusMessage {
+    /**
+     * Transaction Id = (SenderId : sender local transaction Id)
+     * Transaction Id is created from sender and posted via fmq within
+     * TRANSFER_TO message.
+     */
+    uint64_t transactionId;
+    uint32_t bufferId;
+    BufferStatus newStatus;
+    /** Used by the buffer pool. not by client. */
+    int64_t connectionId;
+    /** Valid only when TRANSFER_TO is posted. */
+    int64_t targetConnectionId;
+    /**
+     * Used by the buffer pool, not by client.
+     * Monotonic timestamp in Us since fixed point in time as decided
+     * by the sender of the message
+     */
+    int64_t timestampUs;
+};
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
new file mode 100644
index 0000000..9365d4e
--- /dev/null
+++ b/neuralnetworks/1.1/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.neuralnetworks@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+    ],
+    interfaces: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Model",
+        "Operation",
+        "OperationType",
+    ],
+    gen_java: false,
+}
+
diff --git a/neuralnetworks/1.1/IDevice.hal b/neuralnetworks/1.1/IDevice.hal
new file mode 100644
index 0000000..9d3fc31
--- /dev/null
+++ b/neuralnetworks/1.1/IDevice.hal
@@ -0,0 +1,106 @@
+/*
+ * 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.neuralnetworks@1.1;
+
+import @1.0::ErrorStatus;
+import @1.0::IDevice;
+import @1.0::IPreparedModelCallback;
+
+/**
+ * This interface represents a device driver.
+ */
+interface IDevice extends @1.0::IDevice {
+    /**
+     * Gets the supported operations in a model.
+     *
+     * getSupportedSubgraph indicates which operations of a model are fully
+     * supported by the vendor driver. If an operation may not be supported for
+     * any reason, getSupportedOperations must return false for that operation.
+     *
+     * @param model A model whose operations--and their corresponding
+     *              operands--are to be verified by the driver.
+     * @return status Error status of the call, must be:
+     *                - NONE if successful
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - INVALID_ARGUMENT if provided model is invalid
+     * @return supportedOperations A list of supported operations, where true
+     *                             indicates the operation is supported and
+     *                             false indicates the operation is not
+     *                             supported. The index of "supported"
+     *                             corresponds with the index of the operation
+     *                             it is describing.
+     */
+    getSupportedOperations_1_1(Model model)
+            generates (ErrorStatus status, vec<bool> supportedOperations);
+
+    /**
+     * Creates a prepared model for execution.
+     *
+     * prepareModel is used to make any necessary transformations or alternative
+     * representations to a model for execution, possiblly including
+     * transformations on the constant data, optimization on the model's graph,
+     * or compilation into the device's native binary format. The model itself
+     * is not changed.
+     *
+     * The model is prepared asynchronously with respect to the caller. The
+     * prepareModel function must verify the inputs to the prepareModel function
+     * are correct. If there is an error, prepareModel must immediately invoke
+     * the callback with the appropriate ErrorStatus value and nullptr for the
+     * IPreparedModel, then return with the same ErrorStatus. If the inputs to
+     * the prepareModel function are valid and there is no error, prepareModel
+     * must launch an asynchronous task to prepare the model in the background,
+     * and immediately return from prepareModel with ErrorStatus::NONE. If the
+     * asynchronous task fails to launch, prepareModel must immediately invoke
+     * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the
+     * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE.
+     *
+     * When the asynchronous task has finished preparing the model, it must
+     * immediately invoke the callback function provided as an input to
+     * prepareModel. If the model was prepared successfully, the callback object
+     * must be invoked with an error status of ErrorStatus::NONE and the
+     * produced IPreparedModel object. If an error occurred preparing the model,
+     * the callback object must be invoked with the appropriate ErrorStatus
+     * value and nullptr for the IPreparedModel.
+     *
+     * The only information that may be unknown to the model at this stage is
+     * the shape of the tensors, which may only be known at execution time. As
+     * such, some driver services may return partially prepared models, where
+     * the prepared model can only be finished when it is paired with a set of
+     * inputs to the model. Note that the same prepared model object can be
+     * used with different shapes of inputs on different (possibly concurrent)
+     * executions.
+     *
+     * Multiple threads can call prepareModel on the same model concurrently.
+     *
+     * @param model The model to be prepared for execution.
+     * @param callback A callback object used to return the error status of
+     *                 preparing the model for execution and the prepared model
+     *                 if successful, nullptr otherwise. The callback object's
+     *                 notify function must be called exactly once, even if the
+     *                 model could not be prepared.
+     * @return status Error status of launching a task which prepares the model
+     *                in the background; must be:
+     *                - NONE if preparation task is successfully launched
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if there is an unspecified error
+     *                - INVALID_ARGUMENT if one of the input arguments is
+     *                  invalid
+     */
+    prepareModel_1_1(Model model, IPreparedModelCallback callback)
+          generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
new file mode 100644
index 0000000..18863d3
--- /dev/null
+++ b/neuralnetworks/1.1/types.hal
@@ -0,0 +1,333 @@
+/*
+ * 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.neuralnetworks@1.1;
+
+import @1.0::Operand;
+import @1.0::OperationType;
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.0::OperationType {
+    /**
+     * BatchToSpace for N-D tensors.
+     *
+     * This operation reshapes the "batch" dimension 0 into M + 1 dimensions of shape
+     * block_shape + [batch], interleaves these blocks back into the grid defined by the
+     * spatial dimensions [1, ..., M], to obtain a result with the same rank as the input.
+     * The spatial dimensions of this intermediate result are then optionally cropped
+     * according to the amount to crop to produce the output.
+     * This is the reverse of SpaceToBatch.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: A 1-D Tensor of type TENSOR_INT32, the block sizes for each spatial dimension of the
+     *    input tensor. All values must be >= 1.
+     * 2: A 1-D Tensor of type TENSOR_INT32, the amount to crop for each spatial diemension of the
+     *    input tensor. All values must be >= 0.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    BATCH_TO_SPACE_ND = 29,
+
+    /**
+     * Divides the second tensor from the first tensor, element-wise.
+     *
+     * Takes two input tensors of identical OperandType and compatible dimensions. The output
+     * is the result of dividing the first input tensor by the second, optionally
+     * modified by an activation function.
+     *
+     * Two dimensions are compatible when:
+     *     1. they are equal, or
+     *     2. one of them is 1
+     *
+     * The size of the output is the maximum size along each dimension of the input operands.
+     * It starts with the trailing dimensions, and works its way forward.
+     *
+     * Example:
+     *     input1.dimension =    {4, 1, 2}
+     *     input2.dimension = {5, 4, 3, 1}
+     *     output.dimension = {5, 4, 3, 2}
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the first input.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    DIV = 30,
+
+    /**
+     * Computes the mean of elements across dimensions of a tensor.
+     *
+     * Reduces input tensor along the dimensions given in axis. Unless keep_dims is true,
+     * the rank of the tensor is reduced by 1 for each entry in axis. If keep_dims is
+     * true, the reduced dimensions are retained with length 1.
+     *
+     * If axis has no entries, all dimensions are reduced, and a tensor with a single
+     * element is returned.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     * 1: A 1-D Tensor of type TENSOR_INT32. The dimensions to reduce. If None (the default),
+     *    reduces all dimensions. Must be in the range [-rank(input_tensor), rank(input_tensor)).
+     * 2: An INT32 value, keep_dims. If positive, retains reduced dimensions with length 1.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    MEAN = 31,
+
+    /**
+     * Pads a tensor.
+     *
+     * This operation pads a tensor according to the specified paddings.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: A 2-D Tensor of type TENSOR_INT32. The paddings, before and after for each spatial dimension
+     *    of the input tensor.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    PAD = 32,
+
+    /**
+     * SpaceToBatch for N-D tensors.
+     *
+     * This operation divides "spatial" dimensions [1, ..., M] of the input into a grid of blocks
+     * of shape block_shape, and interleaves these blocks with the "batch" dimension (0) such that
+     * in the output, the spatial dimensions [1, ..., M] correspond to the position within the grid,
+     * and the batch dimension combines both the position within a spatial block and the original
+     * batch position. Prior to division into blocks, the spatial dimensions of the input are
+     * optionally zero padded according to paddings.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: A 1-D Tensor of type TENSOR_INT32, the block sizes for each spatial dimension of the
+     *    input tensor. All values must be >= 1.
+     * 2: A 2-D Tensor of type TENSOR_INT32, the paddings for each spatial diemension of the
+     *    input tensor. All values must be >= 0.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    SPACE_TO_BATCH_ND = 33,
+
+    /**
+     * Removes dimensions of size 1 from the shape of a tensor.
+     *
+     * Given a tensor input, this operation returns a tensor of the same type with all
+     * dimensions of size 1 removed. If you don't want to remove all size 1 dimensions,
+     * you can remove specific size 1 dimensions by specifying axis.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: An 1-D Tensor of type TENSOR_INT32. The dimensions to squeeze. If None (the default),
+     *    squeezes all dimensions. If specified, only squeezes the dimensions listed. The dimension
+     *    index starts at 0. It is an error to squeeze a dimension that is not 1.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0. Contains the same data as input, but has one or more
+     *    dimensions of size 1 removed.
+     */
+    SQUEEZE = 34,
+
+    /**
+     * Extracts a strided slice of a tensor.
+     *
+     * This op extracts a slice of size (end-begin)/stride from the given input tensor.
+    *  Starting at the location specified by begin the slice continues by adding
+     * stride to the index until all dimensions are not less than end. Note that a stride can
+     * be negative, which causes a reverse slice.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: A 1-D Tensor of type TENSOR_INT32, the starts of the dimensions of the input
+     *    tensor to be sliced.
+     * 2: A 1-D Tensor of type TENSOR_INT32, the ends of the dimensions of the input
+     *    tensor to be sliced.
+     * 3: A 1-D Tensor of type TENSOR_INT32, the strides of the dimensions of the input
+     *    tensor to be sliced.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    STRIDED_SLICE = 35,
+
+    /**
+     * Subtracts the second tensor from the first tensor, element-wise.
+     *
+     * Takes two input tensors of identical type and compatible dimensions. The output
+     * is the result of subtracting the second input tensor from the first one, optionally
+     * modified by an activation function.
+     *
+     * Two dimensions are compatible when:
+     *     1. they are equal, or
+     *     2. one of them is 1
+     *
+     * The size of the output is the maximum size along each dimension of the input operands.
+     * It starts with the trailing dimensions, and works its way forward.
+     *
+     * Example:
+     *     input1.dimension =    {4, 1, 2}
+     *     input2.dimension = {5, 4, 3, 1}
+     *     output.dimension = {5, 4, 3, 2}
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the first input.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    SUB = 36,
+
+    /**
+     * Transposes the input tensor, permuting the dimensions according to the perm tensor.
+     *
+     * The returned tensor's dimension i must correspond to the input dimension perm[i].
+     * If perm is not given, it is set to (n-1...0), where n is the rank of the input tensor.
+     * Hence by default, this operation performs a regular matrix transpose on 2-D input Tensors.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: An n-D tensor, specifying the input.
+     * 1: A 1-D Tensor of type TENSOR_INT32, the permutation of the dimensions of the input
+     *    tensor.
+     *
+     * Outputs:
+     * 0: A tensor of the same type as input0.
+     */
+    TRANSPOSE = 37,
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+    /**
+     * The operation type.
+     */
+    OperationType type;
+
+    /**
+     * Describes the table that contains the indexes of the inputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+
+    /**
+     * A byte buffer containing operand data that were copied into the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_COPY.
+     */
+    vec<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand data that were
+     * registered by the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_REFERENCE.
+     */
+    vec<memory> pools;
+};
diff --git a/neuralnetworks/README b/neuralnetworks/README
new file mode 100644
index 0000000..d8c8f5d
--- /dev/null
+++ b/neuralnetworks/README
@@ -0,0 +1,2 @@
+NeuralNetworks sample driver implementation is located at
+frameworks/ml/nn/driver/sample.
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
new file mode 100644
index 0000000..73dc70a
--- /dev/null
+++ b/nfc/1.1/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.nfc@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "INfc.hal",
+        "INfcClientCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.nfc@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "NfcEvent",
+    ],
+    gen_java: true,
+}
+
diff --git a/nfc/1.1/INfc.hal b/nfc/1.1/INfc.hal
new file mode 100644
index 0000000..ea6a571
--- /dev/null
+++ b/nfc/1.1/INfc.hal
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.1;
+
+import @1.1::INfcClientCallback;
+import @1.0::INfc;
+import @1.0::NfcStatus;
+
+interface INfc extends @1.0::INfc {
+    /**
+     * Clears the NFC chip.
+     *
+     * Must be called during factory reset and/or before the first time the HAL is
+     * initialized after a factory reset
+     */
+    factoryReset();
+
+    /**
+     * Enable Power off use cases and close the NFC controller.
+     * Should free all resources.
+     *
+     * This call must enable NFC functionality for off host usecases in power
+     * off use cases, if the device supports power off use cases. If the
+     * device doesn't support power off use cases, this call should be same as
+     * close()
+     *
+     * @return NfcStatus::OK on success and NfcStatus::FAILED on error.
+     */
+    closeForPowerOffCase() generates (NfcStatus status);
+
+    /**
+     * Open call to take the @1.1::INfcClientCallback
+     *
+     * @param clientCallback for sending events and data to client.
+     * @return status NfcStatus::FAILED in case of error,
+     *                NfcStatus::SUCCESS otherwise.
+     */
+    open_1_1(INfcClientCallback clientCallback) generates (NfcStatus status);
+};
diff --git a/nfc/1.1/INfcClientCallback.hal b/nfc/1.1/INfcClientCallback.hal
new file mode 100644
index 0000000..8e1a7bc
--- /dev/null
+++ b/nfc/1.1/INfcClientCallback.hal
@@ -0,0 +1,28 @@
+/*
+ * 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.nfc@1.1;
+
+import @1.0::INfcClientCallback;
+import @1.0::NfcStatus;
+
+interface INfcClientCallback extends @1.0::INfcClientCallback {
+    /**
+     * The callback passed in from the NFC stack that the HAL
+     * can use to pass events back to the stack.
+     */
+    sendEvent_1_1(NfcEvent event, NfcStatus status);
+};
diff --git a/nfc/1.1/types.hal b/nfc/1.1/types.hal
new file mode 100644
index 0000000..2f5ec7f
--- /dev/null
+++ b/nfc/1.1/types.hal
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.nfc@1.1;
+
+import @1.0::NfcEvent;
+
+enum NfcEvent : @1.0::NfcEvent {
+    /** In case of an error, HCI network needs to be re-initialized */
+    HCI_NETWORK_RESET = 7
+};
diff --git a/nfc/1.1/vts/functional/Android.bp b/nfc/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..0ce531f
--- /dev/null
+++ b/nfc/1.1/vts/functional/Android.bp
@@ -0,0 +1,25 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalNfcV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalNfcV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.nfc@1.0",
+        "android.hardware.nfc@1.1",
+    ],
+}
diff --git a/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
new file mode 100644
index 0000000..a5b40d4
--- /dev/null
+++ b/nfc/1.1/vts/functional/VtsHalNfcV1_1TargetTest.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "nfc_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/nfc/1.0/types.h>
+#include <android/hardware/nfc/1.1/INfc.h>
+#include <android/hardware/nfc/1.1/INfcClientCallback.h>
+#include <android/hardware/nfc/1.1/types.h>
+#include <hardware/nfc.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::nfc::V1_1::INfc;
+using ::android::hardware::nfc::V1_1::INfcClientCallback;
+using ::android::hardware::nfc::V1_1::NfcEvent;
+using ::android::hardware::nfc::V1_0::NfcStatus;
+using ::android::hardware::nfc::V1_0::NfcData;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+constexpr char kCallbackNameSendEvent[] = "sendEvent";
+constexpr char kCallbackNameSendData[] = "sendData";
+
+class NfcClientCallbackArgs {
+   public:
+    NfcEvent last_event_;
+    NfcStatus last_status_;
+    NfcData last_data_;
+};
+
+/* Callback class for data & Event. */
+class NfcClientCallback : public ::testing::VtsHalHidlTargetCallbackBase<NfcClientCallbackArgs>,
+                          public INfcClientCallback {
+   public:
+    virtual ~NfcClientCallback() = default;
+
+    /* sendEvent callback function - Records the Event & Status
+     * and notifies the TEST
+     **/
+    Return<void> sendEvent_1_1(NfcEvent event, NfcStatus event_status) override {
+        NfcClientCallbackArgs args;
+        args.last_event_ = event;
+        args.last_status_ = event_status;
+        NotifyFromCallback(kCallbackNameSendEvent, args);
+        return Void();
+    };
+
+    /** NFC 1.1 HAL shouldn't send 1.0 callbacks */
+    Return<void> sendEvent(__attribute__((unused))::android::hardware::nfc::V1_0::NfcEvent event,
+                           __attribute__((unused)) NfcStatus event_status) override {
+        return Void();
+    }
+
+    /* sendData callback function. Records the data and notifies the TEST*/
+    Return<void> sendData(const NfcData& data) override {
+        NfcClientCallbackArgs args;
+        args.last_data_ = data;
+        NotifyFromCallback(kCallbackNameSendData, args);
+        return Void();
+    };
+};
+
+// The main test class for NFC HIDL HAL.
+class NfcHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        nfc_ = ::testing::VtsHalHidlTargetTestBase::getService<INfc>();
+        ASSERT_NE(nfc_, nullptr);
+
+        nfc_cb_ = new NfcClientCallback();
+        ASSERT_NE(nfc_cb_, nullptr);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        /*
+         * Close the hal and then re-open to make sure we are in a predictable
+         * state for all the tests.
+         */
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+        EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+        // Wait for OPEN_CPLT event
+        res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    virtual void TearDown() override {
+        EXPECT_EQ(NfcStatus::OK, nfc_->close());
+        // Wait for CLOSE_CPLT event
+        auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+        EXPECT_TRUE(res.no_timeout);
+        EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+        EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+    }
+
+    sp<INfc> nfc_;
+    sp<NfcClientCallback> nfc_cb_;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class NfcHidlEnvironment : public ::testing::Environment {
+   public:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+   private:
+};
+
+/*
+ * factoryReset
+ * calls factoryReset()
+ * checks status
+ */
+TEST_F(NfcHidlTest, FactoryReset) {
+    nfc_->factoryReset();
+
+    EXPECT_EQ(NfcStatus::OK, nfc_->close());
+    // Wait for CLOSE_CPLT event
+    auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+    EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+    // Wait for OPEN_CPLT event
+    res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+/*
+ * OpenAndClose:
+ * Makes an open call, waits for NfcEvent.OPEN_CPLT
+ * Immediately calls closeforPowerOffCase() and waits for NfcEvent.CLOSE_CPLT
+ */
+TEST_F(NfcHidlTest, OpenAndCloseForPowerOff) {
+    EXPECT_EQ(NfcStatus::OK, nfc_->closeForPowerOffCase());
+    // Wait for CLOSE_CPLT event
+    auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+    EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+    // Wait for OPEN_CPLT event
+    res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+/*
+ * CloseForPowerOffCaseAfterClose:
+ * Calls closeForPowerOffCase()
+ * Calls close() - checks failed status
+ */
+TEST_F(NfcHidlTest, CloseForPowerCaseOffAfterClose) {
+    EXPECT_EQ(NfcStatus::OK, nfc_->closeForPowerOffCase());
+    // Wait for CLOSE_CPLT event
+    auto res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::CLOSE_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+
+    EXPECT_EQ(NfcStatus::FAILED, nfc_->close());
+
+    EXPECT_EQ(NfcStatus::OK, nfc_->open_1_1(nfc_cb_));
+    // Wait for OPEN_CPLT event
+    res = nfc_cb_->WaitForCallback(kCallbackNameSendEvent);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(NfcEvent::OPEN_CPLT, res.args->last_event_);
+    EXPECT_EQ(NfcStatus::OK, res.args->last_status_);
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(new NfcHidlEnvironment);
+    ::testing::InitGoogleTest(&argc, argv);
+
+    std::system("svc nfc disable"); /* Turn off NFC */
+    sleep(5);
+
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+
+    std::system("svc nfc enable"); /* Turn on NFC */
+    sleep(5);
+
+    return status;
+}
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index f4ca1cf..552e33d 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -19,6 +19,8 @@
         "android.hidl.base@1.0",
     ],
     types: [
+        "AudioQuality",
+        "Call",
         "CardStatus",
         "CellConnectionStatus",
         "CellIdentityCdma",
diff --git a/radio/1.2/IRadioResponse.hal b/radio/1.2/IRadioResponse.hal
index c356954..93ec4d7 100644
--- a/radio/1.2/IRadioResponse.hal
+++ b/radio/1.2/IRadioResponse.hal
@@ -72,4 +72,20 @@
      *   RadioError:INTERNAL_ERR
      */
     oneway setLinkCapacityReportingCriteriaResponse(RadioResponseInfo info);
+
+    /**
+     * @param calls Current call list
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:SYSTEM_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:NO_RESOURCES
+     *   RadioError:CANCELLED
+     */
+    oneway getCurrentCallsResponse_1_2(RadioResponseInfo info, vec<Call> calls);
 };
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index f2f0b69..c353645 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -16,6 +16,7 @@
 
 package android.hardware.radio@1.2;
 
+import @1.0::Call;
 import @1.0::CdmaSignalStrength;
 import @1.0::CardState;
 import @1.0::CardStatus;
@@ -125,6 +126,33 @@
     PHYSICAL_CHANNEL_CONFIG = 1 << 4,
 };
 
+/**
+ * Audio codec which is used on GSM, UMTS, and CDMA. These values must be opaque
+ * to the Android framework. Only for display.
+ */
+enum AudioQuality : int32_t {
+    /** Unspecified audio codec */
+    UNSPECIFIED,
+    /** AMR (Narrowband) audio codec */
+    AMR,
+    /** AMR (Wideband) audio codec */
+    AMR_WB,
+    /** GSM Enhanced Full-Rate audio codec */
+    GSM_EFR,
+    /** GSM Full-Rate audio codec */
+    GSM_FR,
+    /** GSM Half-Rate audio codec */
+    GSM_HR,
+    /** Enhanced Variable rate codec */
+    EVRC,
+    /** Enhanced Variable rate codec revision B */
+    EVRC_B,
+    /** Enhanced Variable rate codec (Wideband) */
+    EVRC_WB,
+    /** Enhanced Variable rate codec (Narrowband) */
+    EVRC_NW,
+};
+
 struct NetworkScanRequest {
     ScanType type;
 
@@ -364,3 +392,8 @@
      */
     HANDOVER  = 0x03,
 };
+
+struct Call {
+    @1.0::Call base;
+    AudioQuality audioQuality;
+};
diff --git a/secure_element/1.0/Android.bp b/secure_element/1.0/Android.bp
new file mode 100644
index 0000000..e8081df
--- /dev/null
+++ b/secure_element/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.secure_element@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ISecureElement.hal",
+        "ISecureElementHalCallback.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "LogicalChannelResponse",
+        "SecureElementStatus",
+    ],
+    gen_java: true,
+}
+
diff --git a/secure_element/1.0/ISecureElement.hal b/secure_element/1.0/ISecureElement.hal
new file mode 100644
index 0000000..d1e36f7
--- /dev/null
+++ b/secure_element/1.0/ISecureElement.hal
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.secure_element@1.0;
+
+import ISecureElementHalCallback;
+
+/** According to ISO/IEC 7816 */
+interface ISecureElement {
+    /**
+     * Initializes the Secure Element. This may include updating the applet
+     * and/or vendor-specific initialization.
+     *
+     * HAL service must send onStateChange() with connected equal to true
+     * after all the initialization has been successfully completed.
+     * Clients must wait for a onStateChange(true) before opening channels.
+     *
+     * @param clientCallback callback used to sent status of the SE back to the
+     *                       client
+     */
+    init(ISecureElementHalCallback clientCallback);
+
+    /**
+     * Returns Answer to Reset as per ISO/IEC 7816
+     *
+     * @return response containing the response. Empty vector if Secure Element
+     *                  doesn't support ATR.
+     */
+    getAtr() generates (vec<uint8_t> response);
+
+    /**
+     * Returns the current state of the card.
+     *
+     * This is particularly useful for removable
+     * Secure Elements like UICC, Secure Elements on SD cards etc.
+     *
+     * @return present true if present, false otherwise
+     */
+    isCardPresent() generates (bool present);
+
+    /**
+     * Transmits an APDU command (as per ISO/IEC 7816) to the SE.
+     *
+     * @param data APDU command to be sent
+     * @return response to the command. In case of error in communicating with
+     *                  the secure element, an empty vector is returned.
+     */
+     transmit(vec<uint8_t> data) generates (vec<uint8_t> response);
+
+    /**
+     * Opens a logical channel with the Secure Element, selecting the applet
+     * represented by the Application ID (AID).
+     *
+     * @param aid AID to uniquely identify the applet on the Secure Element
+     * @param p2 P2 paramter of SELECT APDU as per ISO 7816-4
+     * @return status SecureElementStatus::SUCCESS on success,
+     *                SecureElementStatus::CHANNEL_NOT_AVAILABLE if secure
+     *                element has reached the maximum limit on the number of
+     *                channels it can support,
+     *                SecureElementStatus::NO_SUCH_ELEMENT_ERROR if AID provided
+     *                doesn't match any applet on the secure element and
+     *                SecureElementStatus::UNSUPPORTED_OPERATION if operation
+     *                provided by the P2 parameter is not permitted by the
+     *                applet.
+     *                SecureElementStatus::IOERROR if there was an error
+     *                communicating with the Secure Element.
+     * @return response On success, response to SELECT command is returned
+     *                        empty vector on failure.
+     */
+    openLogicalChannel(vec<uint8_t> aid, uint8_t p2)
+        generates (LogicalChannelResponse response, SecureElementStatus status);
+
+
+    /**
+     * Opens a basic channel with the Secure Element, selecting the applet
+     * represented by the Application ID (AID).
+     *
+     * @param aid AID to uniquely identify the applet on the Secure Element
+     * @param p2 P2 paramter of SELECT APDU as per ISO 7816-4
+     * @return status SecureElementStatus::SUCCESS on success,
+     *                SecureElementStatus::CHANNEL_NOT_AVAILABLE if secure
+     *                element has reached the maximum limit on the number of
+     *                channels it can support,
+     *                SecureElementStatus::NO_SUCH_ELEMENT_ERROR if AID provided
+     *                doesn't match any applet on the secure element and
+     *                SecureElementStatus::UNSUPPORTED_OPERATION if operation
+     *                provided by the P2 parameter is not permitted by the
+     *                applet.
+     *                SecureElementStatus::IOERROR if there was an error
+     *                communicating with the Secure Element.
+     * @return selectResponse On success, response to SELECT command is returned
+     *                        empty vector on failure.
+     */
+    openBasicChannel(vec<uint8_t> aid, uint8_t p2)
+        generates (vec<uint8_t> selectResponse, SecureElementStatus status);
+
+    /**
+     * Closes the channel indicated by the channelNumber.
+     *
+     * Closing a basic channel, i.e with channelNumber 0 must return
+     * SecureElementStatus::FAILED.
+     *
+     * @param channelNumber to be closed
+     * @return status SecureElementStatus::SUCCESS on success and
+     *                SecureElementStatus::FAILED on error.
+     */
+    closeChannel(uint8_t channelNumber) generates (SecureElementStatus status);
+};
diff --git a/secure_element/1.0/ISecureElementHalCallback.hal b/secure_element/1.0/ISecureElementHalCallback.hal
new file mode 100644
index 0000000..d11600f
--- /dev/null
+++ b/secure_element/1.0/ISecureElementHalCallback.hal
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.secure_element@1.0;
+
+interface ISecureElementHalCallback {
+    onStateChange(bool connected);
+};
diff --git a/secure_element/1.0/types.hal b/secure_element/1.0/types.hal
new file mode 100644
index 0000000..8150be4
--- /dev/null
+++ b/secure_element/1.0/types.hal
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.secure_element@1.0;
+
+enum SecureElementStatus : uint8_t {
+    SUCCESS               = 0,
+    FAILED                = 1,
+    CHANNEL_NOT_AVAILABLE = 2,
+    NO_SUCH_ELEMENT_ERROR = 3,
+    UNSUPPORTED_OPERATION = 4,
+    IOERROR = 5
+};
+
+struct LogicalChannelResponse {
+    /** Channel number to uniquely identify the channel */
+    uint8_t channelNumber;
+    /** Response to SELECT command as per ISO/IEC 7816 */
+    vec<uint8_t> selectResponse;
+};
diff --git a/secure_element/1.0/vts/functional/Android.bp b/secure_element/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..752df9e
--- /dev/null
+++ b/secure_element/1.0/vts/functional/Android.bp
@@ -0,0 +1,24 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalSecureElementV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalSecureElementV1_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.secure_element@1.0",
+    ],
+}
diff --git a/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
new file mode 100644
index 0000000..2045e44
--- /dev/null
+++ b/secure_element/1.0/vts/functional/VtsHalSecureElementV1_0TargetTest.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "secure_element_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <android/hardware/secure_element/1.0/ISecureElement.h>
+#include <android/hardware/secure_element/1.0/ISecureElementHalCallback.h>
+#include <android/hardware/secure_element/1.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::hardware::secure_element::V1_0::ISecureElement;
+using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback;
+using ::android::hardware::secure_element::V1_0::SecureElementStatus;
+using ::android::hardware::secure_element::V1_0::LogicalChannelResponse;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+using ::testing::VtsHalHidlTargetTestEnvBase;
+
+#define SELECT_ISD \
+    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
+#define SEQUENCE_COUNTER \
+    { 0x80, 0xCA, 0x00, 0xC1, 0x00 }
+#define MANAGE_SELECT \
+    { 0x00, 0xA4, 0x04, 0x00, 0x00 }
+#define CRS_AID \
+    { 0xA0, 0x00, 0x00, 0x01, 0x51, 0x43, 0x52, 0x53, 0x00 }
+
+constexpr char kCallbackNameOnStateChange[] = "onStateChange";
+
+class SecureElementCallbackArgs {
+   public:
+    bool state_;
+};
+
+class SecureElementHalCallback
+    : public ::testing::VtsHalHidlTargetCallbackBase<SecureElementCallbackArgs>,
+      public ISecureElementHalCallback {
+   public:
+    virtual ~SecureElementHalCallback() = default;
+
+    Return<void> onStateChange(bool state) override {
+        SecureElementCallbackArgs args;
+        args.state_ = state;
+        NotifyFromCallback(kCallbackNameOnStateChange, args);
+        return Void();
+    };
+};
+
+class SecureElementHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static SecureElementHidlEnvironment* Instance() {
+        static SecureElementHidlEnvironment* instance = new SecureElementHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<ISecureElement>(); }
+
+   private:
+    SecureElementHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SecureElementHidlEnvironment);
+};
+
+class SecureElementHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        std::string serviceName =
+            SecureElementHidlEnvironment::Instance()->getServiceName<ISecureElement>("eSE1");
+        LOG(INFO) << "get service with name:" << serviceName;
+        ASSERT_FALSE(serviceName.empty());
+        se_ = ::testing::VtsHalHidlTargetTestBase::getService<ISecureElement>(serviceName);
+        ASSERT_NE(se_, nullptr);
+
+        se_cb_ = new SecureElementHalCallback();
+        ASSERT_NE(se_cb_, nullptr);
+    }
+
+    sp<ISecureElement> se_;
+    sp<SecureElementHalCallback> se_cb_;
+};
+
+/*
+ * isCardPresent:
+ * Expects the card to be present
+ */
+TEST_F(SecureElementHidlTest, isCardPresent) {
+    EXPECT_TRUE(se_->isCardPresent());
+}
+
+/*
+ * transmit:
+ * Check status word in the response
+ */
+TEST_F(SecureElementHidlTest, transmit) {
+    std::vector<uint8_t> aid = CRS_AID;
+    SecureElementStatus statusReturned;
+    LogicalChannelResponse response;
+    se_->openLogicalChannel(
+        aid, 0x00,
+        [&statusReturned, &response](LogicalChannelResponse channelResponse,
+                                     SecureElementStatus status) {
+            statusReturned = status;
+            if (status == SecureElementStatus::SUCCESS) {
+                response.channelNumber = channelResponse.channelNumber;
+                response.selectResponse.resize(channelResponse.selectResponse.size());
+                for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) {
+                    response.selectResponse[i] = channelResponse.selectResponse[i];
+                }
+            }
+        });
+    EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
+    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE(1, response.channelNumber);
+    std::vector<uint8_t> command = SELECT_ISD;
+    std::vector<uint8_t> transmitResponse;
+    se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+        transmitResponse.resize(res.size());
+        for (size_t i = 0; i < res.size(); i++) {
+            transmitResponse[i] = res[i];
+        }
+    });
+    EXPECT_LE((unsigned int)3, transmitResponse.size());
+    EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+    EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+    command = SEQUENCE_COUNTER;
+    se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+        transmitResponse.resize(res.size());
+        for (size_t i = 0; i < res.size(); i++) {
+            transmitResponse[i] = res[i];
+        }
+    });
+    EXPECT_LE((unsigned int)3, transmitResponse.size());
+    EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+    EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+    EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
+}
+
+/*
+ * OpenCloseBasicChannel:
+ * If the secure element allows opening of basic channel:
+ *  open channel, check the length of selectResponse and close the channel
+ */
+TEST_F(SecureElementHidlTest, openBasicChannel) {
+    std::vector<uint8_t> aid = CRS_AID;
+    SecureElementStatus statusReturned;
+    std::vector<uint8_t> response;
+    se_->openBasicChannel(aid, 0x00,
+                          [&statusReturned, &response](std::vector<uint8_t> selectResponse,
+                                                       SecureElementStatus status) {
+                              statusReturned = status;
+                              if (status == SecureElementStatus::SUCCESS) {
+                                  response.resize(selectResponse.size());
+                                  for (size_t i = 0; i < selectResponse.size(); i++) {
+                                      response[i] = selectResponse[i];
+                                  }
+                              }
+                          });
+    if (statusReturned == SecureElementStatus::SUCCESS) {
+        EXPECT_LE((unsigned int)3, response.size());
+        std::vector<uint8_t> command = SELECT_ISD;
+        std::vector<uint8_t> transmitResponse;
+        se_->transmit(command, [&transmitResponse](std::vector<uint8_t> res) {
+            transmitResponse.resize(res.size());
+            for (size_t i = 0; i < res.size(); i++) {
+                transmitResponse[i] = res[i];
+            }
+        });
+        EXPECT_LE((unsigned int)3, transmitResponse.size());
+        EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]);
+        EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]);
+        return;
+    }
+    EXPECT_EQ(SecureElementStatus::UNSUPPORTED_OPERATION, statusReturned);
+}
+
+/*
+ * GetATR
+ */
+TEST_F(SecureElementHidlTest, getAtr) {
+    std::vector<uint8_t> atr;
+    se_->getAtr([&atr](std::vector<uint8_t> atrReturned) {
+        atr.resize(atrReturned.size());
+        for (size_t i = 0; i < atrReturned.size(); i++) {
+            atr[i] = atrReturned[i];
+        }
+    });
+    if (atr.size() == 0) {
+        return;
+    }
+    EXPECT_GE((unsigned int)32, atr.size());
+    EXPECT_LE((unsigned int)1, atr.size());
+}
+
+/*
+ * OpenCloseLogicalChannel:
+ * Open Channel
+ * Check status
+ * Close Channel
+ */
+TEST_F(SecureElementHidlTest, openCloseLogicalChannel) {
+    std::vector<uint8_t> aid = CRS_AID;
+    SecureElementStatus statusReturned;
+    LogicalChannelResponse response;
+    se_->openLogicalChannel(
+        aid, 0x00,
+        [&statusReturned, &response](LogicalChannelResponse channelResponse,
+                                     SecureElementStatus status) {
+            statusReturned = status;
+            if (status == SecureElementStatus::SUCCESS) {
+                response.channelNumber = channelResponse.channelNumber;
+                response.selectResponse.resize(channelResponse.selectResponse.size());
+                for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) {
+                    response.selectResponse[i] = channelResponse.selectResponse[i];
+                }
+            }
+        });
+    EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned);
+    EXPECT_LE((unsigned int)3, response.selectResponse.size());
+    EXPECT_LE(1, response.channelNumber);
+    EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber));
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(SecureElementHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SecureElementHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/tests/extension/light/2.0/types.hal b/tests/extension/light/2.0/types.hal
index c05e099..4463cac 100644
--- a/tests/extension/light/2.0/types.hal
+++ b/tests/extension/light/2.0/types.hal
@@ -41,7 +41,7 @@
     /**
      * Sometimes at night, we need it to be day.
      */
-     THE_SUN,
+    THE_SUN,
 };
 
 /**
diff --git a/wifi/1.2/default/ringbuffer.cpp b/wifi/1.2/default/ringbuffer.cpp
index 5511f2f..c126b36 100644
--- a/wifi/1.2/default/ringbuffer.cpp
+++ b/wifi/1.2/default/ringbuffer.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
+
 #include "ringbuffer.h"
 
 namespace android {
@@ -28,6 +30,11 @@
     if (input.size() == 0) {
         return;
     }
+    if (input.size() > maxSize_) {
+        LOG(INFO) << "Oversized message of " << input.size()
+                  << " bytes is dropped";
+        return;
+    }
     data_.push_back(input);
     size_ += input.size() * sizeof(input[0]);
     while (size_ > maxSize_) {
diff --git a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
index 1b332f9..ad5289b 100644
--- a/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
+++ b/wifi/1.2/default/tests/ringbuffer_unit_tests.cpp
@@ -81,6 +81,15 @@
     buffer_.append(input);
     ASSERT_TRUE(buffer_.getData().empty());
 }
+
+TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) {
+    const std::vector<uint8_t> input(maxBufferSize_, '0');
+    const std::vector<uint8_t> input2(maxBufferSize_ + 1, '1');
+    buffer_.append(input);
+    buffer_.append(input2);
+    ASSERT_EQ(1u, buffer_.getData().size());
+    EXPECT_EQ(input, buffer_.getData().front());
+}
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace wifi
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index 05ea638..201b8e4 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -123,34 +123,118 @@
         std::string cur_file_name(dp->d_name);
         struct stat cur_file_stat;
         std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
-        if (stat(cur_file_path.c_str(), &cur_file_stat) != -1) {
-            if (cur_file_stat.st_mtime < delete_files_before) {
-                if (unlink(cur_file_path.c_str()) != 0) {
-                    LOG(ERROR) << "Error deleting file " << strerror(errno);
-                    success = false;
-                }
-            }
-        } else {
+        if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
             LOG(ERROR) << "Failed to get file stat for " << cur_file_path
                        << ": " << strerror(errno);
             success = false;
+            continue;
+        }
+        if (cur_file_stat.st_mtime >= delete_files_before) {
+            continue;
+        }
+        if (unlink(cur_file_path.c_str()) != 0) {
+            LOG(ERROR) << "Error deleting file " << strerror(errno);
+            success = false;
         }
     }
     return success;
 }
 
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name,
+                     size_t file_name_len) {
+    std::array<char, 32 * 1024> read_buf;
+    ssize_t llen =
+        sprintf(read_buf.data(),
+                "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
+                kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
+                st.st_gid, static_cast<int>(st.st_nlink),
+                static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
+                major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
+                minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
+    if (write(out_fd, read_buf.data(), llen) == -1) {
+        LOG(ERROR) << "Error writing cpio header to file " << file_name << " "
+                   << strerror(errno);
+        return false;
+    }
+    if (write(out_fd, file_name, file_name_len) == -1) {
+        LOG(ERROR) << "Error writing filename to file " << file_name << " "
+                   << strerror(errno);
+        return false;
+    }
+
+    // NUL Pad header up to 4 multiple bytes.
+    llen = (llen + file_name_len) % 4;
+    if (llen != 0) {
+        const uint32_t zero = 0;
+        if (write(out_fd, &zero, 4 - llen) == -1) {
+            LOG(ERROR) << "Error padding 0s to file " << file_name << " "
+                       << strerror(errno);
+            return false;
+        }
+    }
+    return true;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
+    // writing content of file
+    std::array<char, 32 * 1024> read_buf;
+    ssize_t llen = st.st_size;
+    size_t n_error = 0;
+    while (llen > 0) {
+        ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
+        if (bytes_read == -1) {
+            LOG(ERROR) << "Error reading file " << strerror(errno);
+            return ++n_error;
+        }
+        llen -= bytes_read;
+        if (write(out_fd, read_buf.data(), bytes_read) == -1) {
+            LOG(ERROR) << "Error writing data to file " << strerror(errno);
+            return ++n_error;
+        }
+        if (bytes_read == 0) {  // this should never happen, but just in case
+                                // to unstuck from while loop
+            LOG(ERROR) << "Unexpected read result for " << strerror(errno);
+            n_error++;
+            break;
+        }
+    }
+    llen = st.st_size % 4;
+    if (llen != 0) {
+        const uint32_t zero = 0;
+        if (write(out_fd, &zero, 4 - llen) == -1) {
+            LOG(ERROR) << "Error padding 0s to file " << strerror(errno);
+            return ++n_error;
+        }
+    }
+    return n_error;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteFileTrailer(int out_fd) {
+    std::array<char, 4096> read_buf;
+    read_buf.fill(0);
+    if (write(out_fd, read_buf.data(),
+              sprintf(read_buf.data(), "070701%040X%056X%08XTRAILER!!!", 1,
+                      0x0b, 0) +
+                  4) == -1) {
+        LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
+        return false;
+    }
+    return true;
+}
+
 // Archives all files in |input_dir| and writes result into |out_fd|
 // Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
 // portion
-size_t cpioFilesInDir(int out_fd, const char* input_dir) {
+size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
     struct dirent* dp;
     size_t n_error = 0;
-    char read_buf[32 * 1024];
     DIR* dir_dump = opendir(input_dir);
     if (!dir_dump) {
         LOG(ERROR) << "Failed to open directory: " << strerror(errno);
-        n_error++;
-        return n_error;
+        return ++n_error;
     }
     unique_fd dir_auto_closer(dirfd(dir_dump));
     while ((dp = readdir(dir_dump))) {
@@ -158,99 +242,36 @@
             continue;
         }
         std::string cur_file_name(dp->d_name);
-        const size_t file_name_len =
-            cur_file_name.size() + 1;  // string.size() does not include the
-                                       // null terminator. The cpio FreeBSD file
-                                       // header expects the null character to
-                                       // be included in the length.
+        // string.size() does not include the null terminator. The cpio FreeBSD
+        // file header expects the null character to be included in the length.
+        const size_t file_name_len = cur_file_name.size() + 1;
         struct stat st;
-        ssize_t llen;
         const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
-        if (stat(cur_file_path.c_str(), &st) != -1) {
-            const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
-            unique_fd file_auto_closer(fd_read);
-            if (fd_read == -1) {
-                LOG(ERROR) << "Failed to read file " << cur_file_path << " "
-                           << strerror(errno);
-                n_error++;
-                continue;
-            }
-            llen = sprintf(
-                read_buf,
-                "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
-                kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid,
-                st.st_gid, static_cast<int>(st.st_nlink),
-                static_cast<int>(st.st_mtime), static_cast<int>(st.st_size),
-                major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
-                minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
-            if (write(out_fd, read_buf, llen) == -1) {
-                LOG(ERROR) << "Error writing cpio header to file "
-                           << cur_file_path << " " << strerror(errno);
-                n_error++;
-                return n_error;
-            }
-            if (write(out_fd, cur_file_name.c_str(), file_name_len) == -1) {
-                LOG(ERROR) << "Error writing filename to file " << cur_file_path
-                           << " " << strerror(errno);
-                n_error++;
-                return n_error;
-            }
-
-            // NUL Pad header up to 4 multiple bytes.
-            llen = (llen + file_name_len) % 4;
-            if (llen != 0) {
-                const uint32_t zero = 0;
-                if (write(out_fd, &zero, 4 - llen) == -1) {
-                    LOG(ERROR) << "Error padding 0s to file " << cur_file_path
-                               << " " << strerror(errno);
-                    n_error++;
-                    return n_error;
-                }
-            }
-
-            // writing content of file
-            llen = st.st_size;
-            while (llen > 0) {
-                ssize_t bytes_read = read(fd_read, read_buf, sizeof(read_buf));
-                if (bytes_read == -1) {
-                    LOG(ERROR) << "Error reading file " << cur_file_path << " "
-                               << strerror(errno);
-                    n_error++;
-                    return n_error;
-                }
-                llen -= bytes_read;
-                if (write(out_fd, read_buf, bytes_read) == -1) {
-                    LOG(ERROR) << "Error writing data to file " << cur_file_path
-                               << " " << strerror(errno);
-                    n_error++;
-                    return n_error;
-                }
-                if (bytes_read ==
-                    0) {  // this should never happen, but just in case
-                          // to unstuck from while loop
-                    LOG(ERROR) << "Unexpected file size for " << cur_file_path
-                               << " " << strerror(errno);
-                    n_error++;
-                    break;
-                }
-            }
-            llen = st.st_size % 4;
-            if (llen != 0) {
-                const uint32_t zero = 0;
-                write(out_fd, &zero, 4 - llen);
-            }
-        } else {
+        if (stat(cur_file_path.c_str(), &st) == -1) {
             LOG(ERROR) << "Failed to get file stat for " << cur_file_path
                        << ": " << strerror(errno);
             n_error++;
+            continue;
+        }
+        const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
+        if (fd_read == -1) {
+            LOG(ERROR) << "Failed to open file " << cur_file_path << " "
+                       << strerror(errno);
+            n_error++;
+            continue;
+        }
+        unique_fd file_auto_closer(fd_read);
+        if (!cpioWriteHeader(out_fd, st, cur_file_name.c_str(),
+                             file_name_len)) {
+            return ++n_error;
+        }
+        size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
+        if (write_error) {
+            return n_error + write_error;
         }
     }
-    memset(read_buf, 0, sizeof(read_buf));
-    if (write(out_fd, read_buf,
-              sprintf(read_buf, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0) +
-                  4) == -1) {
-        LOG(ERROR) << "Error writing trailing bytes " << strerror(errno);
-        n_error++;
+    if (!cpioWriteFileTrailer(out_fd)) {
+        return ++n_error;
     }
     return n_error;
 }
@@ -541,7 +562,7 @@
         if (!writeRingbufferFilesInternal()) {
             LOG(ERROR) << "Error writing files to flash";
         }
-        uint32_t n_error = cpioFilesInDir(fd, kTombstoneFolderPath);
+        uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
         if (n_error != 0) {
             LOG(ERROR) << n_error << " errors occured in cpio function";
         }
diff --git a/wifi/hostapd/1.0/IHostapd.hal b/wifi/hostapd/1.0/IHostapd.hal
index 4dc7bf8..3493398 100644
--- a/wifi/hostapd/1.0/IHostapd.hal
+++ b/wifi/hostapd/1.0/IHostapd.hal
@@ -157,4 +157,12 @@
      *         |HostapdStatusCode.FAILURE_IFACE_UNKNOWN|
      */
     removeAccessPoint(string ifaceName) generates(HostapdStatus status);
+
+    /**
+     * Terminate the service.
+     * This must de-register the service and clear all state. If this HAL
+     * supports the lazy HAL protocol, then this may trigger daemon to exit and
+     * wait to be restarted.
+     */
+    oneway terminate();
 };
diff --git a/wifi/supplicant/1.1/ISupplicant.hal b/wifi/supplicant/1.1/ISupplicant.hal
index 508a545..f3ec0fc 100644
--- a/wifi/supplicant/1.1/ISupplicant.hal
+++ b/wifi/supplicant/1.1/ISupplicant.hal
@@ -54,4 +54,12 @@
      *         |SupplicantStatusCode.FAILURE_IFACE_UNKOWN|
      */
     removeInterface(IfaceInfo ifaceInfo) generates (SupplicantStatus status);
+
+    /**
+     * Terminate the service.
+     * This must de-register the service and clear all state. If this HAL
+     * supports the lazy HAL protocol, then this may trigger daemon to exit and
+     * wait to be restarted.
+     */
+    oneway terminate();
 };