Merge "NFC: Update VTS test" am: 3bce41d5ec am: 4d3c1ea989 am: d4cffbf1ec
am: 7b51c28e24

Change-Id: I4123a9bfa33c0a65ddee0d20ab3a316d5171c4cf
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
new file mode 100644
index 0000000..2f0c936
--- /dev/null
+++ b/audio/2.0/Android.bp
@@ -0,0 +1,106 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.audio@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio@2.0",
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IDevicesFactory.hal",
+        "IPrimaryDevice.hal",
+        "IStream.hal",
+        "IStreamIn.hal",
+        "IStreamOut.hal",
+        "IStreamOutCallback.hal",
+    ],
+    out: [
+        "android/hardware/audio/2.0/types.cpp",
+        "android/hardware/audio/2.0/DeviceAll.cpp",
+        "android/hardware/audio/2.0/DevicesFactoryAll.cpp",
+        "android/hardware/audio/2.0/PrimaryDeviceAll.cpp",
+        "android/hardware/audio/2.0/StreamAll.cpp",
+        "android/hardware/audio/2.0/StreamInAll.cpp",
+        "android/hardware/audio/2.0/StreamOutAll.cpp",
+        "android/hardware/audio/2.0/StreamOutCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.audio@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio@2.0",
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IDevicesFactory.hal",
+        "IPrimaryDevice.hal",
+        "IStream.hal",
+        "IStreamIn.hal",
+        "IStreamOut.hal",
+        "IStreamOutCallback.hal",
+    ],
+    out: [
+        "android/hardware/audio/2.0/types.h",
+        "android/hardware/audio/2.0/IDevice.h",
+        "android/hardware/audio/2.0/IHwDevice.h",
+        "android/hardware/audio/2.0/BnHwDevice.h",
+        "android/hardware/audio/2.0/BpHwDevice.h",
+        "android/hardware/audio/2.0/BsDevice.h",
+        "android/hardware/audio/2.0/IDevicesFactory.h",
+        "android/hardware/audio/2.0/IHwDevicesFactory.h",
+        "android/hardware/audio/2.0/BnHwDevicesFactory.h",
+        "android/hardware/audio/2.0/BpHwDevicesFactory.h",
+        "android/hardware/audio/2.0/BsDevicesFactory.h",
+        "android/hardware/audio/2.0/IPrimaryDevice.h",
+        "android/hardware/audio/2.0/IHwPrimaryDevice.h",
+        "android/hardware/audio/2.0/BnHwPrimaryDevice.h",
+        "android/hardware/audio/2.0/BpHwPrimaryDevice.h",
+        "android/hardware/audio/2.0/BsPrimaryDevice.h",
+        "android/hardware/audio/2.0/IStream.h",
+        "android/hardware/audio/2.0/IHwStream.h",
+        "android/hardware/audio/2.0/BnHwStream.h",
+        "android/hardware/audio/2.0/BpHwStream.h",
+        "android/hardware/audio/2.0/BsStream.h",
+        "android/hardware/audio/2.0/IStreamIn.h",
+        "android/hardware/audio/2.0/IHwStreamIn.h",
+        "android/hardware/audio/2.0/BnHwStreamIn.h",
+        "android/hardware/audio/2.0/BpHwStreamIn.h",
+        "android/hardware/audio/2.0/BsStreamIn.h",
+        "android/hardware/audio/2.0/IStreamOut.h",
+        "android/hardware/audio/2.0/IHwStreamOut.h",
+        "android/hardware/audio/2.0/BnHwStreamOut.h",
+        "android/hardware/audio/2.0/BpHwStreamOut.h",
+        "android/hardware/audio/2.0/BsStreamOut.h",
+        "android/hardware/audio/2.0/IStreamOutCallback.h",
+        "android/hardware/audio/2.0/IHwStreamOutCallback.h",
+        "android/hardware/audio/2.0/BnHwStreamOutCallback.h",
+        "android/hardware/audio/2.0/BpHwStreamOutCallback.h",
+        "android/hardware/audio/2.0/BsStreamOutCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio@2.0",
+    generated_sources: ["android.hardware.audio@2.0_genc++"],
+    generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/audio/2.0/Android.mk b/audio/2.0/Android.mk
new file mode 100644
index 0000000..f8767ec
--- /dev/null
+++ b/audio/2.0/Android.mk
@@ -0,0 +1,46 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio@2.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/audio/V2_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IDevice.hal
+$(GEN): $(LOCAL_PATH)/IDevicesFactory.hal
+$(GEN): $(LOCAL_PATH)/IPrimaryDevice.hal
+$(GEN): $(LOCAL_PATH)/IStream.hal
+$(GEN): $(LOCAL_PATH)/IStreamIn.hal
+$(GEN): $(LOCAL_PATH)/IStreamOut.hal
+$(GEN): $(LOCAL_PATH)/IStreamOutCallback.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.audio@2.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/audio/2.0/IDevice.hal b/audio/2.0/IDevice.hal
new file mode 100644
index 0000000..2b5329b
--- /dev/null
+++ b/audio/2.0/IDevice.hal
@@ -0,0 +1,246 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import IStreamIn;
+import IStreamOut;
+
+interface IDevice {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    /*
+     * 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.
+     * @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,
+            AudioOutputFlag flags) 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.
+     * @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,
+            AudioInputFlag flags,
+            AudioSource source) 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.
+     *
+     * @return hwAvSync HW synchronization source
+     */
+    getHwAvSync() generates (AudioHwSync hwAvSync);
+
+    /*
+     * Sets whether the screen is on. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_KEY_SCREEN_STATE on the legacy HAL.
+     *
+     * @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.
+     *
+     * @param keys parameter keys.
+     * @return retval operation completion status.
+     * @return parameters parameter key value pairs.
+     */
+    getParameters(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.
+     *
+     * @param parameters parameter key value pairs.
+     * @return retval operation completion status.
+     */
+    setParameters(vec<ParameterValue> parameters) generates (Result retval);
+
+    /*
+     * Dumps information about the stream into the provided file descriptor.
+     * This is used for the dumpsys facility.
+     *
+     * @param fd dump file descriptor.
+     */
+    debugDump(handle fd);
+};
diff --git a/audio/2.0/IDevicesFactory.hal b/audio/2.0/IDevicesFactory.hal
new file mode 100644
index 0000000..0ef6bc5
--- /dev/null
+++ b/audio/2.0/IDevicesFactory.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import IDevice;
+
+interface IDevicesFactory {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    enum Device : int32_t {
+        PRIMARY,
+        A2DP,
+        USB,
+        R_SUBMIX,
+        STUB
+    };
+
+    /*
+     * 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/2.0/IPrimaryDevice.hal b/audio/2.0/IPrimaryDevice.hal
new file mode 100644
index 0000000..f1dd56e
--- /dev/null
+++ b/audio/2.0/IPrimaryDevice.hal
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import IDevice;
+
+interface IPrimaryDevice extends IDevice {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    /*
+     * 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.
+     *
+     * @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.
+     *
+     * @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.
+     *
+     * @param enabled whether HAC mode is enabled.
+     * @return retval operation completion status.
+     */
+    setHacEnabled(bool enabled) generates (Result retval);
+};
diff --git a/audio/2.0/IStream.hal b/audio/2.0/IStream.hal
new file mode 100644
index 0000000..8de7851
--- /dev/null
+++ b/audio/2.0/IStream.hal
@@ -0,0 +1,294 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import android.hardware.audio.effect@2.0::IEffect;
+
+interface IStream {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    /*
+     * 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 sampling rates of the stream. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES on the
+     * legacy HAL.
+     *
+     * @return sampleRateHz supported sample rates.
+     */
+    getSupportedSampleRates() generates (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.
+     *
+     * @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 (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.
+     *
+     * @return masks supported audio masks.
+     */
+    getSupportedChannelMasks() generates (vec<AudioChannelMask> masks);
+
+    /*
+     * Sets the channel mask of the stream. Calling this method is equivalent to
+     * setting AUDIO_PARAMETER_STREAM_CHANNELS on the legacy HAL.
+     *
+     * @param format audio format.
+     * @return retval operation completion status.
+     */
+    setChannelMask(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.
+     *
+     * @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, 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.
+     *
+     * @return device set of device(s) which this stream is connected to.
+     */
+    getDevice() generates (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.
+     *
+     * @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.
+     *
+     * @param keys parameter keys.
+     * @return retval operation completion status.
+     * @return parameters parameter key value pairs.
+     */
+    getParameters(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.
+     *
+     * @param parameters parameter key value pairs.
+     * @return retval operation completion status.
+     */
+    setParameters(vec<ParameterValue> parameters) generates (Result retval);
+
+    /*
+     * Dumps information about the stream into the provided file descriptor.
+     * This is used for the dumpsys facility.
+     *
+     * @param fd dump file descriptor.
+     */
+    debugDump(handle fd);
+
+    /*
+     * 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/2.0/IStreamIn.hal b/audio/2.0/IStreamIn.hal
new file mode 100644
index 0000000..9a96f71
--- /dev/null
+++ b/audio/2.0/IStreamIn.hal
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import IStream;
+
+interface IStreamIn extends IStream {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    /*
+     * Returns the source descriptor of the input stream. Calling this method is
+     * equivalent to getting AUDIO_PARAMETER_STREAM_INPUT_SOURCE on the legacy
+     * HAL.
+     *
+     * @return retval operation completion status.
+     * @return source audio source.
+     */
+    getAudioSource() generates (Result retval, AudioSource source);
+
+    /*
+     * Set the input gain for the audio driver.
+     *
+     * @param gain 1.0f is unity, 0.0f is zero.
+     * @result retval operation completion status.
+     */
+    setGain(float gain) generates (Result retval);
+
+    /*
+     * 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;
+        uint64_t read;
+    };
+
+    /*
+     * Set up required transports for receiving audio buffers from the driver.
+     *
+     * The transport consists of two message queues: one is used for passing
+     * audio data from the driver to the client, another is used for reporting
+     * read operation status (amount of bytes actually read or error code),
+     * see ReadStatus structure definition.
+     *
+     * @param frameSize the size of a single frame, in bytes.
+     * @param framesCount the number of frames in a buffer.
+     * @param threadPriority priority of the thread that performs reads.
+     * @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 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.
+     */
+    prepareForReading(
+            uint32_t frameSize, uint32_t framesCount,
+            ThreadPriority threadPriority)
+    generates (
+            Result retval,
+            fmq_sync<uint8_t> dataMQ, fmq_sync<ReadStatus> statusMQ);
+
+    /*
+     * 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);
+};
diff --git a/audio/2.0/IStreamOut.hal b/audio/2.0/IStreamOut.hal
new file mode 100644
index 0000000..336684f
--- /dev/null
+++ b/audio/2.0/IStreamOut.hal
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.0;
+import IStream;
+import IStreamOutCallback;
+
+interface IStreamOut extends IStream {
+    typedef android.hardware.audio@2.0::Result Result;
+
+    /*
+     * 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.
+     *
+     * @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.
+     */
+    setVolume(float left, float right) generates (Result retval);
+
+    /*
+     * Data structure passed back to the client via status message queue
+     * of 'write' operation.
+     *
+     * Possible values of 'writeRetval' 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.
+     *
+     * Possible values of 'presentationPositionRetval' field (must only
+     * be considered if 'writeRetval' field is set to 'OK'):
+     *  - OK, presentation position retrieved successfully;
+     *  - INVALID_ARGUMENTS, indicates that the position can't be retrieved;
+     *  - INVALID_OPERATION, retrieving presentation position isn't supported;
+     */
+    struct WriteStatus {
+        Result writeRetval;
+        uint64_t written;
+        Result presentationPositionRetval;
+        uint64_t frames;    // presentation position
+        TimeSpec timeStamp; // presentation position
+    };
+
+    /*
+     * Set up required transports for passing audio buffers to the driver.
+     *
+     * The transport consists of two message queues: one is used for passing
+     * audio data from the client to the driver, another is used for reporting
+     * write operation status (amount of bytes actually written or error code),
+     * and the presentation position immediately after the write, see
+     * WriteStatus structure definition.
+     *
+     * @param frameSize the size of a single frame, in bytes.
+     * @param framesCount the number of frames in a buffer.
+     * @param threadPriority priority of the thread that performs writes.
+     * @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 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.
+     */
+    prepareForWriting(
+            uint32_t frameSize, uint32_t framesCount,
+            ThreadPriority threadPriority)
+    generates (
+            Result retval,
+            fmq_sync<uint8_t> dataMQ, fmq_sync<WriteStatus> statusMQ);
+
+    /*
+     * Return the number of audio frames written by the audio DSP to DAC since
+     * the output has exited standby.
+     *
+     * @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.
+     *
+     * @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.
+     *
+     * @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'.
+     *
+     * 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.
+     *
+     * @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/2.0/IStreamOutCallback.hal b/audio/2.0/IStreamOutCallback.hal
new file mode 100644
index 0000000..cdb38de
--- /dev/null
+++ b/audio/2.0/IStreamOutCallback.hal
@@ -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.
+ */
+
+package android.hardware.audio@2.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/2.0/default/Android.mk b/audio/2.0/default/Android.mk
new file mode 100644
index 0000000..eeea92c
--- /dev/null
+++ b/audio/2.0/default/Android.mk
@@ -0,0 +1,81 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio@2.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    Conversions.cpp \
+    Device.cpp \
+    DevicesFactory.cpp \
+    ParametersUtil.cpp \
+    PrimaryDevice.cpp \
+    Stream.cpp \
+    StreamIn.cpp \
+    StreamOut.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    libfmq \
+    libhardware \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libmediautils \
+    libutils \
+    android.hardware.audio@2.0 \
+    android.hardware.audio.common@2.0 \
+    android.hardware.audio.common@2.0-util \
+
+LOCAL_WHOLE_STATIC_LIBRARIES := libmedia_helper
+
+include $(BUILD_SHARED_LIBRARY)
+
+#
+# Service
+#
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio@2.0-service
+LOCAL_INIT_RC := android.hardware.audio@2.0-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.audio@2.0 \
+    android.hardware.audio.common@2.0 \
+    android.hardware.audio.effect@2.0 \
+    android.hardware.soundtrigger@2.0 \
+    android.hardware.broadcastradio@1.0
+
+ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
+LOCAL_MULTILIB := 32
+else
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+endif
+
+include $(BUILD_EXECUTABLE)
diff --git a/audio/2.0/default/Conversions.cpp b/audio/2.0/default/Conversions.cpp
new file mode 100644
index 0000000..e669185
--- /dev/null
+++ b/audio/2.0/default/Conversions.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+
+#include "Conversions.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+std::string deviceAddressToHal(const DeviceAddress& address) {
+    // HAL assumes that the address is NUL-terminated.
+    char halAddress[AUDIO_DEVICE_MAX_ADDRESS_LEN];
+    memset(halAddress, 0, sizeof(halAddress));
+    uint32_t halDevice = static_cast<uint32_t>(address.device);
+    const bool isInput = (halDevice & AUDIO_DEVICE_BIT_IN) != 0;
+    if (isInput) halDevice &= ~AUDIO_DEVICE_BIT_IN;
+    if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_A2DP) != 0)
+            || (isInput && (halDevice & AUDIO_DEVICE_IN_BLUETOOTH_A2DP) != 0)) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%02X:%02X:%02X:%02X:%02X:%02X",
+                address.address.mac[0], address.address.mac[1], address.address.mac[2],
+                address.address.mac[3], address.address.mac[4], address.address.mac[5]);
+    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_IP) != 0)
+            || (isInput && (halDevice & AUDIO_DEVICE_IN_IP) != 0)) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%d.%d.%d.%d",
+                address.address.ipv4[0], address.address.ipv4[1],
+                address.address.ipv4[2], address.address.ipv4[3]);
+    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_ALL_USB) != 0)
+            || (isInput && (halDevice & AUDIO_DEVICE_IN_ALL_USB) != 0)) {
+        snprintf(halAddress, sizeof(halAddress),
+                "card=%d;device=%d",
+                address.address.alsa.card, address.address.alsa.device);
+    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_BUS) != 0)
+            || (isInput && (halDevice & AUDIO_DEVICE_IN_BUS) != 0)) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%s", address.busAddress.c_str());
+    } else if ((!isInput && (halDevice & AUDIO_DEVICE_OUT_REMOTE_SUBMIX)) != 0
+            || (isInput && (halDevice & AUDIO_DEVICE_IN_REMOTE_SUBMIX) != 0)) {
+        snprintf(halAddress, sizeof(halAddress),
+                "%s", address.rSubmixAddress.c_str());
+    }
+    return halAddress;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Conversions.h b/audio/2.0/default/Conversions.h
new file mode 100644
index 0000000..ebda5c5
--- /dev/null
+++ b/audio/2.0/default/Conversions.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_V2_0_Conversions_H_
+#define android_hardware_audio_V2_0_Conversions_H_
+
+#include <string>
+
+#include <android/hardware/audio/2.0/types.h>
+#include <system/audio.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::DeviceAddress;
+
+std::string deviceAddressToHal(const DeviceAddress& address);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_Conversions_H_
diff --git a/audio/2.0/default/Device.cpp b/audio/2.0/default/Device.cpp
new file mode 100644
index 0000000..8a51cd7
--- /dev/null
+++ b/audio/2.0/default/Device.cpp
@@ -0,0 +1,297 @@
+ /*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DeviceHAL"
+//#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <memory.h>
+#include <string.h>
+
+#include <android/log.h>
+
+#include "Conversions.h"
+#include "Device.h"
+#include "HidlUtils.h"
+#include "StreamIn.h"
+#include "StreamOut.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Device::Device(audio_hw_device_t* device)
+        : mDevice(device) {
+}
+
+Device::~Device() {
+    int status = audio_hw_device_close(mDevice);
+    ALOGW_IF(status, "Error closing audio hw device %p: %s", mDevice, strerror(-status));
+    mDevice = nullptr;
+}
+
+Result Device::analyzeStatus(const char* funcName, int status) {
+    if (status != 0) {
+        ALOGW("Device %p %s: %s", mDevice, funcName, strerror(-status));
+    }
+    switch (status) {
+        case 0: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        case -ENOSYS: return Result::NOT_SUPPORTED;
+        default: return Result::INVALID_STATE;
+    }
+}
+
+char* Device::halGetParameters(const char* keys) {
+    return mDevice->get_parameters(mDevice, keys);
+}
+
+int Device::halSetParameters(const char* keysAndValues) {
+    return mDevice->set_parameters(mDevice, keysAndValues);
+}
+
+// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+Return<Result> Device::initCheck()  {
+    return analyzeStatus("init_check", mDevice->init_check(mDevice));
+}
+
+Return<Result> Device::setMasterVolume(float volume)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mDevice->set_master_volume != NULL) {
+        retval = analyzeStatus("set_master_volume", mDevice->set_master_volume(mDevice, volume));
+    }
+    return retval;
+}
+
+Return<void> Device::getMasterVolume(getMasterVolume_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    float volume = 0;
+    if (mDevice->get_master_volume != NULL) {
+        retval = analyzeStatus("get_master_volume", mDevice->get_master_volume(mDevice, &volume));
+    }
+    _hidl_cb(retval, volume);
+    return Void();
+}
+
+Return<Result> Device::setMicMute(bool mute)  {
+    return analyzeStatus("set_mic_mute", mDevice->set_mic_mute(mDevice, mute));
+}
+
+Return<void> Device::getMicMute(getMicMute_cb _hidl_cb)  {
+    bool mute = false;
+    Result retval = analyzeStatus("get_mic_mute", mDevice->get_mic_mute(mDevice, &mute));
+    _hidl_cb(retval, mute);
+    return Void();
+}
+
+Return<Result> Device::setMasterMute(bool mute)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mDevice->set_master_mute != NULL) {
+        retval = analyzeStatus("set_master_mute", mDevice->set_master_mute(mDevice, mute));
+    }
+    return retval;
+}
+
+Return<void> Device::getMasterMute(getMasterMute_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    bool mute = false;
+    if (mDevice->get_master_mute != NULL) {
+        retval = analyzeStatus("get_master_mute", mDevice->get_master_mute(mDevice, &mute));
+    }
+    _hidl_cb(retval, mute);
+    return Void();
+}
+
+Return<void> Device::getInputBufferSize(
+        const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    HidlUtils::audioConfigToHal(config, &halConfig);
+    size_t halBufferSize = mDevice->get_input_buffer_size(mDevice, &halConfig);
+    Result retval(Result::INVALID_ARGUMENTS);
+    uint64_t bufferSize = 0;
+    if (halBufferSize != 0) {
+        retval = Result::OK;
+        bufferSize = halBufferSize;
+    }
+    _hidl_cb(retval, bufferSize);
+    return Void();
+}
+
+Return<void> Device::openOutputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioOutputFlag flags,
+        openOutputStream_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    HidlUtils::audioConfigToHal(config, &halConfig);
+    audio_stream_out_t *halStream;
+    ALOGV("open_output_stream handle: %d devices: %x flags: %#x "
+            "srate: %d format %#x channels %x address %s",
+            ioHandle,
+            static_cast<audio_devices_t>(device.device), static_cast<audio_output_flags_t>(flags),
+            halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
+            deviceAddressToHal(device).c_str());
+    int status = mDevice->open_output_stream(
+            mDevice,
+            ioHandle,
+            static_cast<audio_devices_t>(device.device),
+            static_cast<audio_output_flags_t>(flags),
+            &halConfig,
+            &halStream,
+            deviceAddressToHal(device).c_str());
+    ALOGV("open_output_stream status %d stream %p", status, halStream);
+    sp<IStreamOut> streamOut;
+    if (status == OK) {
+        streamOut = new StreamOut(mDevice, halStream);
+    }
+    AudioConfig suggestedConfig;
+    HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
+    _hidl_cb(analyzeStatus("open_output_stream", status), streamOut, suggestedConfig);
+    return Void();
+}
+
+Return<void> Device::openInputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioInputFlag flags,
+        AudioSource source,
+        openInputStream_cb _hidl_cb)  {
+    audio_config_t halConfig;
+    HidlUtils::audioConfigToHal(config, &halConfig);
+    audio_stream_in_t *halStream;
+    ALOGV("open_input_stream handle: %d devices: %x flags: %#x "
+            "srate: %d format %#x channels %x address %s source %d",
+            ioHandle,
+            static_cast<audio_devices_t>(device.device), static_cast<audio_input_flags_t>(flags),
+            halConfig.sample_rate, halConfig.format, halConfig.channel_mask,
+            deviceAddressToHal(device).c_str(), static_cast<audio_source_t>(source));
+    int status = mDevice->open_input_stream(
+            mDevice,
+            ioHandle,
+            static_cast<audio_devices_t>(device.device),
+            &halConfig,
+            &halStream,
+            static_cast<audio_input_flags_t>(flags),
+            deviceAddressToHal(device).c_str(),
+            static_cast<audio_source_t>(source));
+    ALOGV("open_input_stream status %d stream %p", status, halStream);
+    sp<IStreamIn> streamIn;
+    if (status == OK) {
+        streamIn = new StreamIn(mDevice, halStream);
+    }
+    AudioConfig suggestedConfig;
+    HidlUtils::audioConfigFromHal(halConfig, &suggestedConfig);
+    _hidl_cb(analyzeStatus("open_input_stream", status), streamIn, suggestedConfig);
+    return Void();
+}
+
+Return<bool> Device::supportsAudioPatches() {
+    return version() >= AUDIO_DEVICE_API_VERSION_3_0;
+}
+
+Return<void> Device::createAudioPatch(
+        const hidl_vec<AudioPortConfig>& sources,
+        const hidl_vec<AudioPortConfig>& sinks,
+        createAudioPatch_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    AudioPatchHandle patch = 0;
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        std::unique_ptr<audio_port_config[]> halSources(HidlUtils::audioPortConfigsToHal(sources));
+        std::unique_ptr<audio_port_config[]> halSinks(HidlUtils::audioPortConfigsToHal(sinks));
+        audio_patch_handle_t halPatch;
+        retval = analyzeStatus(
+                "create_audio_patch",
+                mDevice->create_audio_patch(
+                        mDevice,
+                        sources.size(), &halSources[0],
+                        sinks.size(), &halSinks[0],
+                        &halPatch));
+        if (retval == Result::OK) {
+            patch = static_cast<AudioPatchHandle>(halPatch);
+        }
+    }
+    _hidl_cb(retval, patch);
+    return Void();
+}
+
+Return<Result> Device::releaseAudioPatch(int32_t patch)  {
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        return analyzeStatus(
+                "release_audio_patch",
+                mDevice->release_audio_patch(mDevice, static_cast<audio_patch_handle_t>(patch)));
+    }
+    return Result::NOT_SUPPORTED;
+}
+
+Return<void> Device::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  {
+    audio_port halPort;
+    HidlUtils::audioPortToHal(port, &halPort);
+    Result retval = analyzeStatus("get_audio_port", mDevice->get_audio_port(mDevice, &halPort));
+    AudioPort resultPort = port;
+    if (retval == Result::OK) {
+        HidlUtils::audioPortFromHal(halPort, &resultPort);
+    }
+    _hidl_cb(retval, resultPort);
+    return Void();
+}
+
+Return<Result> Device::setAudioPortConfig(const AudioPortConfig& config)  {
+    if (version() >= AUDIO_DEVICE_API_VERSION_3_0) {
+        struct audio_port_config halPortConfig;
+        HidlUtils::audioPortConfigToHal(config, &halPortConfig);
+        return analyzeStatus(
+                "set_audio_port_config", mDevice->set_audio_port_config(mDevice, &halPortConfig));
+    }
+    return Result::NOT_SUPPORTED;
+}
+
+Return<AudioHwSync> Device::getHwAvSync()  {
+    int halHwAvSync;
+    Result retval = getParam(AudioParameter::keyHwAvSync, &halHwAvSync);
+    return retval == Result::OK ? halHwAvSync : AUDIO_HW_SYNC_INVALID;
+}
+
+Return<Result> Device::setScreenState(bool turnedOn)  {
+    return setParam(AudioParameter::keyScreenState, turnedOn);
+}
+
+Return<void> Device::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    getParametersImpl(keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Device::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return setParametersImpl(parameters);
+}
+
+Return<void> Device::debugDump(const hidl_handle& fd)  {
+    if (fd->numFds == 1) {
+        analyzeStatus("dump", mDevice->dump(mDevice, fd->data[0]));
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Device.h b/audio/2.0/default/Device.h
new file mode 100644
index 0000000..46177fc
--- /dev/null
+++ b/audio/2.0/default/Device.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
+
+#include <memory>
+
+#include <media/AudioParameter.h>
+#include <hardware/audio.h>
+
+#include <android/hardware/audio/2.0/IDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioConfig;
+using ::android::hardware::audio::common::V2_0::AudioHwSync;
+using ::android::hardware::audio::common::V2_0::AudioInputFlag;
+using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
+using ::android::hardware::audio::common::V2_0::AudioPatchHandle;
+using ::android::hardware::audio::common::V2_0::AudioPort;
+using ::android::hardware::audio::common::V2_0::AudioPortConfig;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Device : public IDevice, public ParametersUtil {
+    explicit Device(audio_hw_device_t* device);
+
+    // Methods from ::android::hardware::audio::V2_0::IDevice follow.
+    Return<Result> initCheck()  override;
+    Return<Result> setMasterVolume(float volume)  override;
+    Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb)  override;
+    Return<Result> setMicMute(bool mute)  override;
+    Return<void> getMicMute(getMicMute_cb _hidl_cb)  override;
+    Return<Result> setMasterMute(bool mute)  override;
+    Return<void> getMasterMute(getMasterMute_cb _hidl_cb)  override;
+    Return<void> getInputBufferSize(
+            const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  override;
+    Return<void> openOutputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioOutputFlag flags,
+            openOutputStream_cb _hidl_cb)  override;
+    Return<void> openInputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioInputFlag flags,
+            AudioSource source,
+            openInputStream_cb _hidl_cb)  override;
+    Return<bool> supportsAudioPatches()  override;
+    Return<void> createAudioPatch(
+            const hidl_vec<AudioPortConfig>& sources,
+            const hidl_vec<AudioPortConfig>& sinks,
+            createAudioPatch_cb _hidl_cb)  override;
+    Return<Result> releaseAudioPatch(int32_t patch)  override;
+    Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  override;
+    Return<Result> setAudioPortConfig(const AudioPortConfig& config)  override;
+    Return<AudioHwSync> getHwAvSync()  override;
+    Return<Result> setScreenState(bool turnedOn)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+
+    // Utility methods for extending interfaces.
+    Result analyzeStatus(const char* funcName, int status);
+    audio_hw_device_t* device() const { return mDevice; }
+
+  private:
+    audio_hw_device_t *mDevice;
+
+    virtual ~Device();
+
+    // Methods from ParametersUtil.
+    char* halGetParameters(const char* keys) override;
+    int halSetParameters(const char* keysAndValues) override;
+
+    uint32_t version() const { return mDevice->common.version; }
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICE_H
diff --git a/audio/2.0/default/DevicesFactory.cpp b/audio/2.0/default/DevicesFactory.cpp
new file mode 100644
index 0000000..8825107
--- /dev/null
+++ b/audio/2.0/default/DevicesFactory.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "DevicesFactoryHAL"
+
+#include <string.h>
+
+#include <android/log.h>
+
+#include "Device.h"
+#include "DevicesFactory.h"
+#include "PrimaryDevice.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+// static
+const char* DevicesFactory::deviceToString(IDevicesFactory::Device device) {
+    switch (device) {
+        case IDevicesFactory::Device::PRIMARY: return AUDIO_HARDWARE_MODULE_ID_PRIMARY;
+        case IDevicesFactory::Device::A2DP: return AUDIO_HARDWARE_MODULE_ID_A2DP;
+        case IDevicesFactory::Device::USB: return AUDIO_HARDWARE_MODULE_ID_USB;
+        case IDevicesFactory::Device::R_SUBMIX: return AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX;
+        case IDevicesFactory::Device::STUB: return AUDIO_HARDWARE_MODULE_ID_STUB;
+    }
+}
+
+// static
+int DevicesFactory::loadAudioInterface(const char *if_name, audio_hw_device_t **dev)
+{
+    const hw_module_t *mod;
+    int rc;
+
+    rc = hw_get_module_by_class(AUDIO_HARDWARE_MODULE_ID, if_name, &mod);
+    if (rc) {
+        ALOGE("%s couldn't load audio hw module %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    rc = audio_hw_device_open(mod, dev);
+    if (rc) {
+        ALOGE("%s couldn't open audio hw device in %s.%s (%s)", __func__,
+                AUDIO_HARDWARE_MODULE_ID, if_name, strerror(-rc));
+        goto out;
+    }
+    if ((*dev)->common.version < AUDIO_DEVICE_API_VERSION_MIN) {
+        ALOGE("%s wrong audio hw device version %04x", __func__, (*dev)->common.version);
+        rc = -EINVAL;
+        audio_hw_device_close(*dev);
+        goto out;
+    }
+    return OK;
+
+out:
+    *dev = NULL;
+    return rc;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
+Return<void> DevicesFactory::openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  {
+    audio_hw_device_t *halDevice;
+    int halStatus = loadAudioInterface(deviceToString(device), &halDevice);
+    Result retval(Result::OK);
+    sp<IDevice> result;
+    if (halStatus == OK) {
+        if (device == IDevicesFactory::Device::PRIMARY) {
+            result = new PrimaryDevice(halDevice);
+        } else {
+            result = new ::android::hardware::audio::V2_0::implementation::Device(halDevice);
+        }
+    } else if (halStatus == -EINVAL) {
+        retval = Result::NOT_INITIALIZED;
+    } else {
+        retval = Result::INVALID_ARGUMENTS;
+    }
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* /* name */) {
+    return new DevicesFactory();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/DevicesFactory.h b/audio/2.0/default/DevicesFactory.h
new file mode 100644
index 0000000..b046f9f
--- /dev/null
+++ b/audio/2.0/default/DevicesFactory.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
+
+#include <hardware/audio.h>
+
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IDevicesFactory;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct DevicesFactory : public IDevicesFactory {
+    // Methods from ::android::hardware::audio::V2_0::IDevicesFactory follow.
+    Return<void> openDevice(IDevicesFactory::Device device, openDevice_cb _hidl_cb)  override;
+
+  private:
+    static const char* deviceToString(IDevicesFactory::Device device);
+    static int loadAudioInterface(const char *if_name, audio_hw_device_t **dev);
+
+};
+
+extern "C" IDevicesFactory* HIDL_FETCH_IDevicesFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_DEVICESFACTORY_H
diff --git a/audio/2.0/default/ParametersUtil.cpp b/audio/2.0/default/ParametersUtil.cpp
new file mode 100644
index 0000000..75a60b9
--- /dev/null
+++ b/audio/2.0/default/ParametersUtil.cpp
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#include "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Result ParametersUtil::getParam(const char* name, bool* value) {
+    String8 halValue;
+    Result retval = getParam(name, &halValue);
+    *value = false;
+    if (retval == Result::OK) {
+        *value = !(halValue == AudioParameter::valueOff);
+    }
+    return retval;
+}
+
+Result ParametersUtil::getParam(const char* name, int* value) {
+    const String8 halName(name);
+    AudioParameter keys;
+    keys.addKey(halName);
+    std::unique_ptr<AudioParameter> params = getParams(keys);
+    status_t halStatus = params->getInt(halName, *value);
+    return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+}
+
+Result ParametersUtil::getParam(const char* name, String8* value) {
+    const String8 halName(name);
+    AudioParameter keys;
+    keys.addKey(halName);
+    std::unique_ptr<AudioParameter> params = getParams(keys);
+    status_t halStatus = params->get(halName, *value);
+    return halStatus == OK ? Result::OK : Result::INVALID_ARGUMENTS;
+}
+
+void ParametersUtil::getParametersImpl(
+        const hidl_vec<hidl_string>& keys,
+        std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb)  {
+    AudioParameter halKeys;
+    for (size_t i = 0; i < keys.size(); ++i) {
+        halKeys.addKey(String8(keys[i].c_str()));
+    }
+    std::unique_ptr<AudioParameter> halValues = getParams(halKeys);
+    Result retval(Result::INVALID_ARGUMENTS);
+    hidl_vec<ParameterValue> result;
+    if (halValues->size() > 0) {
+        result.resize(halValues->size());
+        String8 halKey, halValue;
+        for (size_t i = 0; i < halValues->size(); ++i) {
+            status_t status = halValues->getAt(i, halKey, halValue);
+            if (status != OK) {
+                result.resize(0);
+                break;
+            }
+            result[i].key = halKey.string();
+            result[i].value = halValue.string();
+        }
+        if (result.size() != 0) {
+            retval = Result::OK;
+        }
+    }
+    cb(retval, result);
+}
+
+std::unique_ptr<AudioParameter> ParametersUtil::getParams(const AudioParameter& keys) {
+    String8 paramsAndValues;
+    char *halValues = halGetParameters(keys.keysToString().string());
+    if (halValues != NULL) {
+        paramsAndValues.setTo(halValues);
+        free(halValues);
+    } else {
+        paramsAndValues.clear();
+    }
+    return std::unique_ptr<AudioParameter>(new AudioParameter(paramsAndValues));
+}
+
+Result ParametersUtil::setParam(const char* name, bool value) {
+    AudioParameter param;
+    param.add(String8(name), String8(value ? AudioParameter::valueOn : AudioParameter::valueOff));
+    return setParams(param);
+}
+
+Result ParametersUtil::setParam(const char* name, int value) {
+    AudioParameter param;
+    param.addInt(String8(name), value);
+    return setParams(param);
+}
+
+Result ParametersUtil::setParam(const char* name, const char* value) {
+    AudioParameter param;
+    param.add(String8(name), String8(value));
+    return setParams(param);
+}
+
+Result ParametersUtil::setParametersImpl(const hidl_vec<ParameterValue>& parameters)  {
+    AudioParameter params;
+    for (size_t i = 0; i < parameters.size(); ++i) {
+        params.add(String8(parameters[i].key.c_str()), String8(parameters[i].value.c_str()));
+    }
+    return setParams(params);
+}
+
+Result ParametersUtil::setParams(const AudioParameter& param) {
+    int halStatus = halSetParameters(param.toString().string());
+    if (halStatus == OK)
+        return Result::OK;
+    else if (halStatus == -ENOSYS)
+        return Result::INVALID_STATE;
+    else
+        return Result::INVALID_ARGUMENTS;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/ParametersUtil.h b/audio/2.0/default/ParametersUtil.h
new file mode 100644
index 0000000..49036dc
--- /dev/null
+++ b/audio/2.0/default/ParametersUtil.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_V2_0_ParametersUtil_H_
+#define android_hardware_audio_V2_0_ParametersUtil_H_
+
+#include <functional>
+#include <memory>
+
+#include <android/hardware/audio/2.0/types.h>
+#include <hidl/HidlSupport.h>
+#include <media/AudioParameter.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+class ParametersUtil {
+  public:
+    Result getParam(const char* name, bool* value);
+    Result getParam(const char* name, int* value);
+    Result getParam(const char* name, String8* value);
+    void getParametersImpl(
+            const hidl_vec<hidl_string>& keys,
+            std::function<void(Result retval, const hidl_vec<ParameterValue>& parameters)> cb);
+    std::unique_ptr<AudioParameter> getParams(const AudioParameter& keys);
+    Result setParam(const char* name, bool value);
+    Result setParam(const char* name, int value);
+    Result setParam(const char* name, const char* value);
+    Result setParametersImpl(const hidl_vec<ParameterValue>& parameters);
+    Result setParams(const AudioParameter& param);
+
+  protected:
+    virtual ~ParametersUtil() {}
+
+    virtual char* halGetParameters(const char* keys) = 0;
+    virtual int halSetParameters(const char* keysAndValues) = 0;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_ParametersUtil_H_
diff --git a/audio/2.0/default/PrimaryDevice.cpp b/audio/2.0/default/PrimaryDevice.cpp
new file mode 100644
index 0000000..905203b
--- /dev/null
+++ b/audio/2.0/default/PrimaryDevice.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PrimaryDeviceHAL"
+
+#include "PrimaryDevice.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+PrimaryDevice::PrimaryDevice(audio_hw_device_t* device)
+        : mDevice(new Device(device)) {
+}
+
+PrimaryDevice::~PrimaryDevice() {}
+
+// Methods from ::android::hardware::audio::V2_0::IDevice follow.
+Return<Result> PrimaryDevice::initCheck()  {
+    return mDevice->initCheck();
+}
+
+Return<Result> PrimaryDevice::setMasterVolume(float volume)  {
+    return mDevice->setMasterVolume(volume);
+}
+
+Return<void> PrimaryDevice::getMasterVolume(getMasterVolume_cb _hidl_cb)  {
+    return mDevice->getMasterVolume(_hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setMicMute(bool mute)  {
+    return mDevice->setMicMute(mute);
+}
+
+Return<void> PrimaryDevice::getMicMute(getMicMute_cb _hidl_cb)  {
+    return mDevice->getMicMute(_hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setMasterMute(bool mute)  {
+    return mDevice->setMasterMute(mute);
+}
+
+Return<void> PrimaryDevice::getMasterMute(getMasterMute_cb _hidl_cb)  {
+    return mDevice->getMasterMute(_hidl_cb);
+}
+
+Return<void> PrimaryDevice::getInputBufferSize(
+        const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  {
+    return mDevice->getInputBufferSize(config, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::openOutputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioOutputFlag flags,
+        openOutputStream_cb _hidl_cb)  {
+    return mDevice->openOutputStream(ioHandle, device, config, flags, _hidl_cb);
+}
+
+Return<void> PrimaryDevice::openInputStream(
+        int32_t ioHandle,
+        const DeviceAddress& device,
+        const AudioConfig& config,
+        AudioInputFlag flags,
+        AudioSource source,
+        openInputStream_cb _hidl_cb)  {
+    return mDevice->openInputStream(ioHandle, device, config, flags, source, _hidl_cb);
+}
+
+Return<bool> PrimaryDevice::supportsAudioPatches() {
+    return mDevice->supportsAudioPatches();
+}
+
+Return<void> PrimaryDevice::createAudioPatch(
+        const hidl_vec<AudioPortConfig>& sources,
+        const hidl_vec<AudioPortConfig>& sinks,
+        createAudioPatch_cb _hidl_cb)  {
+    return mDevice->createAudioPatch(sources, sinks, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::releaseAudioPatch(int32_t patch)  {
+    return mDevice->releaseAudioPatch(patch);
+}
+
+Return<void> PrimaryDevice::getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  {
+    return mDevice->getAudioPort(port, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setAudioPortConfig(const AudioPortConfig& config)  {
+    return mDevice->setAudioPortConfig(config);
+}
+
+Return<AudioHwSync> PrimaryDevice::getHwAvSync()  {
+    return mDevice->getHwAvSync();
+}
+
+Return<Result> PrimaryDevice::setScreenState(bool turnedOn)  {
+    return mDevice->setScreenState(turnedOn);
+}
+
+Return<void> PrimaryDevice::getParameters(
+        const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    return mDevice->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> PrimaryDevice::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mDevice->setParameters(parameters);
+}
+
+Return<void> PrimaryDevice::debugDump(const hidl_handle& fd)  {
+    return mDevice->debugDump(fd);
+}
+
+
+// Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
+Return<Result> PrimaryDevice::setVoiceVolume(float volume)  {
+    return mDevice->analyzeStatus(
+            "set_voice_volume",
+            mDevice->device()->set_voice_volume(mDevice->device(), volume));
+}
+
+Return<Result> PrimaryDevice::setMode(AudioMode mode)  {
+    return mDevice->analyzeStatus(
+            "set_mode",
+            mDevice->device()->set_mode(mDevice->device(), static_cast<audio_mode_t>(mode)));
+}
+
+Return<void> PrimaryDevice::getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AudioParameter::keyBtNrec, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setBtScoNrecEnabled(bool enabled)  {
+    return mDevice->setParam(AudioParameter::keyBtNrec, enabled);
+}
+
+Return<void> PrimaryDevice::getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setBtScoWidebandEnabled(bool enabled)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_BT_SCO_WB, enabled);
+}
+
+Return<void> PrimaryDevice::getTtyMode(getTtyMode_cb _hidl_cb)  {
+    int halMode;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_TTY_MODE, &halMode);
+    TtyMode mode = retval == Result::OK ? TtyMode(halMode) : TtyMode::OFF;
+    _hidl_cb(retval, mode);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setTtyMode(IPrimaryDevice::TtyMode mode)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_TTY_MODE, static_cast<int>(mode));
+}
+
+Return<void> PrimaryDevice::getHacEnabled(getHacEnabled_cb _hidl_cb)  {
+    bool enabled;
+    Result retval = mDevice->getParam(AUDIO_PARAMETER_KEY_HAC, &enabled);
+    _hidl_cb(retval, enabled);
+    return Void();
+}
+
+Return<Result> PrimaryDevice::setHacEnabled(bool enabled)  {
+    return mDevice->setParam(AUDIO_PARAMETER_KEY_HAC, enabled);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/PrimaryDevice.h b/audio/2.0/default/PrimaryDevice.h
new file mode 100644
index 0000000..d95511b
--- /dev/null
+++ b/audio/2.0/default/PrimaryDevice.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
+
+#include <android/hardware/audio/2.0/IPrimaryDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Device.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioConfig;
+using ::android::hardware::audio::common::V2_0::AudioInputFlag;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioOutputFlag;
+using ::android::hardware::audio::common::V2_0::AudioPort;
+using ::android::hardware::audio::common::V2_0::AudioPortConfig;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IDevice;
+using ::android::hardware::audio::V2_0::IPrimaryDevice;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct PrimaryDevice : public IPrimaryDevice {
+    explicit PrimaryDevice(audio_hw_device_t* device);
+
+    // Methods from ::android::hardware::audio::V2_0::IDevice follow.
+    Return<Result> initCheck()  override;
+    Return<Result> setMasterVolume(float volume)  override;
+    Return<void> getMasterVolume(getMasterVolume_cb _hidl_cb)  override;
+    Return<Result> setMicMute(bool mute)  override;
+    Return<void> getMicMute(getMicMute_cb _hidl_cb)  override;
+    Return<Result> setMasterMute(bool mute)  override;
+    Return<void> getMasterMute(getMasterMute_cb _hidl_cb)  override;
+    Return<void> getInputBufferSize(
+            const AudioConfig& config, getInputBufferSize_cb _hidl_cb)  override;
+    Return<void> openOutputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioOutputFlag flags,
+            openOutputStream_cb _hidl_cb)  override;
+    Return<void> openInputStream(
+            int32_t ioHandle,
+            const DeviceAddress& device,
+            const AudioConfig& config,
+            AudioInputFlag flags,
+            AudioSource source,
+            openInputStream_cb _hidl_cb)  override;
+    Return<bool> supportsAudioPatches()  override;
+    Return<void> createAudioPatch(
+            const hidl_vec<AudioPortConfig>& sources,
+            const hidl_vec<AudioPortConfig>& sinks,
+            createAudioPatch_cb _hidl_cb)  override;
+    Return<Result> releaseAudioPatch(int32_t patch)  override;
+    Return<void> getAudioPort(const AudioPort& port, getAudioPort_cb _hidl_cb)  override;
+    Return<Result> setAudioPortConfig(const AudioPortConfig& config)  override;
+    Return<AudioHwSync> getHwAvSync()  override;
+    Return<Result> setScreenState(bool turnedOn)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IPrimaryDevice follow.
+    Return<Result> setVoiceVolume(float volume)  override;
+    Return<Result> setMode(AudioMode mode)  override;
+    Return<void> getBtScoNrecEnabled(getBtScoNrecEnabled_cb _hidl_cb)  override;
+    Return<Result> setBtScoNrecEnabled(bool enabled)  override;
+    Return<void> getBtScoWidebandEnabled(getBtScoWidebandEnabled_cb _hidl_cb)  override;
+    Return<Result> setBtScoWidebandEnabled(bool enabled)  override;
+    Return<void> getTtyMode(getTtyMode_cb _hidl_cb)  override;
+    Return<Result> setTtyMode(IPrimaryDevice::TtyMode mode)  override;
+    Return<void> getHacEnabled(getHacEnabled_cb _hidl_cb)  override;
+    Return<Result> setHacEnabled(bool enabled)  override;
+
+  private:
+    sp<Device> mDevice;
+
+    virtual ~PrimaryDevice();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_PRIMARYDEVICE_H
diff --git a/audio/2.0/default/Stream.cpp b/audio/2.0/default/Stream.cpp
new file mode 100644
index 0000000..62b34a3
--- /dev/null
+++ b/audio/2.0/default/Stream.cpp
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+#include <inttypes.h>
+
+#define LOG_TAG "StreamHAL"
+
+#include <hardware/audio.h>
+#include <hardware/audio_effect.h>
+#include <media/TypeConverter.h>
+#include <android/log.h>
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+#include "Conversions.h"
+#include "EffectMap.h"
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+Stream::Stream(audio_stream_t* stream)
+        : mStream(stream) {
+}
+
+Stream::~Stream() {
+    mStream = nullptr;
+}
+
+// static
+Result Stream::analyzeStatus(const char* funcName, int status, int ignoreError) {
+    if (status != 0 && status != -ignoreError) {
+        ALOGW("Error from HAL stream in function %s: %s", funcName, strerror(-status));
+    }
+    switch (status) {
+        case 0: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        case -ENOSYS: return Result::NOT_SUPPORTED;
+        default: return Result::INVALID_STATE;
+    }
+}
+
+char* Stream::halGetParameters(const char* keys) {
+    return mStream->get_parameters(mStream, keys);
+}
+
+int Stream::halSetParameters(const char* keysAndValues) {
+    return mStream->set_parameters(mStream, keysAndValues);
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> Stream::getFrameSize()  {
+    // Needs to be implemented by interface subclasses. But can't be declared as pure virtual,
+    // since interface subclasses implementation do not inherit from this class.
+    LOG_ALWAYS_FATAL("Stream::getFrameSize is pure abstract");
+    return uint64_t {};
+}
+
+Return<uint64_t> Stream::getFrameCount()  {
+    int halFrameCount;
+    Result retval = getParam(AudioParameter::keyFrameCount, &halFrameCount);
+    return retval == Result::OK ? halFrameCount : 0;
+}
+
+Return<uint64_t> Stream::getBufferSize()  {
+    return mStream->get_buffer_size(mStream);
+}
+
+Return<uint32_t> Stream::getSampleRate()  {
+    return mStream->get_sample_rate(mStream);
+}
+
+Return<void> Stream::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedSamplingRates, &halListValue);
+    hidl_vec<uint32_t> sampleRates;
+    SortedVector<uint32_t> halSampleRates;
+    if (result == Result::OK) {
+        halSampleRates = samplingRatesFromString(
+                halListValue.string(), AudioParameter::valueListSeparator);
+        sampleRates.setToExternal(halSampleRates.editArray(), halSampleRates.size());
+    }
+    _hidl_cb(sampleRates);
+    return Void();
+}
+
+Return<Result> Stream::setSampleRate(uint32_t sampleRateHz)  {
+    return setParam(AudioParameter::keySamplingRate, static_cast<int>(sampleRateHz));
+}
+
+Return<AudioChannelMask> Stream::getChannelMask()  {
+    return AudioChannelMask(mStream->get_channels(mStream));
+}
+
+Return<void> Stream::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedChannels, &halListValue);
+    hidl_vec<AudioChannelMask> channelMasks;
+    SortedVector<audio_channel_mask_t> halChannelMasks;
+    if (result == Result::OK) {
+        halChannelMasks = channelMasksFromString(
+                halListValue.string(), AudioParameter::valueListSeparator);
+        channelMasks.resize(halChannelMasks.size());
+        for (size_t i = 0; i < halChannelMasks.size(); ++i) {
+            channelMasks[i] = AudioChannelMask(halChannelMasks[i]);
+        }
+    }
+     _hidl_cb(channelMasks);
+    return Void();
+}
+
+Return<Result> Stream::setChannelMask(AudioChannelMask mask)  {
+    return setParam(AudioParameter::keyChannels, static_cast<int>(mask));
+}
+
+Return<AudioFormat> Stream::getFormat()  {
+    return AudioFormat(mStream->get_format(mStream));
+}
+
+Return<void> Stream::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    String8 halListValue;
+    Result result = getParam(AudioParameter::keyStreamSupportedFormats, &halListValue);
+    hidl_vec<AudioFormat> formats;
+    Vector<audio_format_t> halFormats;
+    if (result == Result::OK) {
+        halFormats = formatsFromString(halListValue.string(), AudioParameter::valueListSeparator);
+        formats.resize(halFormats.size());
+        for (size_t i = 0; i < halFormats.size(); ++i) {
+            formats[i] = AudioFormat(halFormats[i]);
+        }
+    }
+     _hidl_cb(formats);
+    return Void();
+}
+
+Return<Result> Stream::setFormat(AudioFormat format)  {
+    return setParam(AudioParameter::keyFormat, static_cast<int>(format));
+}
+
+Return<void> Stream::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    uint32_t halSampleRate = mStream->get_sample_rate(mStream);
+    audio_channel_mask_t halMask = mStream->get_channels(mStream);
+    audio_format_t halFormat = mStream->get_format(mStream);
+    _hidl_cb(halSampleRate, AudioChannelMask(halMask), AudioFormat(halFormat));
+    return Void();
+}
+
+Return<Result> Stream::addEffect(uint64_t effectId)  {
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus("add_audio_effect", mStream->add_audio_effect(mStream, halEffect));
+    } else {
+        ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<Result> Stream::removeEffect(uint64_t effectId)  {
+    effect_handle_t halEffect = EffectMap::getInstance().get(effectId);
+    if (halEffect != NULL) {
+        return analyzeStatus(
+                "remove_audio_effect", mStream->remove_audio_effect(mStream, halEffect));
+    } else {
+        ALOGW("Invalid effect ID passed from client: %" PRIu64, effectId);
+        return Result::INVALID_ARGUMENTS;
+    }
+}
+
+Return<Result> Stream::standby()  {
+    return analyzeStatus("standby", mStream->standby(mStream));
+}
+
+Return<AudioDevice> Stream::getDevice()  {
+    return AudioDevice(mStream->get_device(mStream));
+}
+
+Return<Result> Stream::setDevice(const DeviceAddress& address)  {
+    char* halDeviceAddress =
+            audio_device_address_to_parameter(
+                    static_cast<audio_devices_t>(address.device),
+                    deviceAddressToHal(address).c_str());
+    AudioParameter params((String8(halDeviceAddress)));
+    free(halDeviceAddress);
+    params.addInt(
+            String8(AudioParameter::keyRouting), static_cast<audio_devices_t>(address.device));
+    return setParams(params);
+}
+
+Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return setParam(
+            connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
+            deviceAddressToHal(address).c_str());
+}
+
+Return<Result> Stream::setHwAvSync(uint32_t hwAvSync)  {
+    return setParam(AudioParameter::keyStreamHwAvSync, static_cast<int>(hwAvSync));
+}
+
+Return<void> Stream::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    getParametersImpl(keys, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Stream::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return setParametersImpl(parameters);
+}
+
+Return<void> Stream::debugDump(const hidl_handle& fd)  {
+    if (fd->numFds == 1) {
+        analyzeStatus("dump", mStream->dump(mStream, fd->data[0]));
+    }
+    return Void();
+}
+
+Return<Result>  Stream::start() {
+    return Result::NOT_SUPPORTED;
+}
+
+Return<Result>  Stream::stop() {
+    return Result::NOT_SUPPORTED;
+}
+
+Return<void>  Stream::createMmapBuffer(int32_t minSizeFrames __unused,
+                                       createMmapBuffer_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapBufferInfo info;
+    _hidl_cb(retval, info);
+    return Void();
+}
+
+Return<void>  Stream::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapPosition position;
+    _hidl_cb(retval, position);
+    return Void();
+}
+
+Return<Result> Stream::close()  {
+    return Result::NOT_SUPPORTED;
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/Stream.h b/audio/2.0/default/Stream.h
new file mode 100644
index 0000000..73afe05
--- /dev/null
+++ b/audio/2.0/default/Stream.h
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
+
+#include <android/hardware/audio/2.0/IStream.h>
+#include <hardware/audio.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "ParametersUtil.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Stream : public IStream, public ParametersUtil {
+    explicit Stream(audio_stream_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+    Return<Result> close()  override;
+
+    // Utility methods for extending interfaces.
+    static Result analyzeStatus(const char* funcName, int status, int ignoreError = OK);
+
+  private:
+    audio_stream_t *mStream;
+
+    virtual ~Stream();
+
+    // Methods from ParametersUtil.
+    char* halGetParameters(const char* keys) override;
+    int halSetParameters(const char* keysAndValues) override;
+};
+
+
+template <typename T>
+struct StreamMmap : public RefBase {
+    explicit StreamMmap(T* stream) : mStream(stream) {}
+
+    Return<Result> start();
+    Return<Result> stop();
+    Return<void> createMmapBuffer(
+            int32_t minSizeFrames, size_t frameSize, IStream::createMmapBuffer_cb _hidl_cb);
+    Return<void> getMmapPosition(IStream::getMmapPosition_cb _hidl_cb);
+
+ private:
+   StreamMmap() {}
+
+   T *mStream;
+};
+
+template <typename T>
+Return<Result> StreamMmap<T>::start() {
+    if (mStream->start == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->start(mStream);
+    return Stream::analyzeStatus("start", result);
+}
+
+template <typename T>
+Return<Result> StreamMmap<T>::stop() {
+    if (mStream->stop == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->stop(mStream);
+    return Stream::analyzeStatus("stop", result);
+}
+
+template <typename T>
+Return<void> StreamMmap<T>::createMmapBuffer(int32_t minSizeFrames, size_t frameSize,
+                                             IStream::createMmapBuffer_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapBufferInfo info;
+    native_handle_t* hidlHandle = nullptr;
+
+    if (mStream->create_mmap_buffer != NULL) {
+        struct audio_mmap_buffer_info halInfo;
+        retval = Stream::analyzeStatus(
+                "create_mmap_buffer",
+                mStream->create_mmap_buffer(mStream, minSizeFrames, &halInfo));
+        if (retval == Result::OK) {
+            hidlHandle = native_handle_create(1, 0);
+            hidlHandle->data[0] = halInfo.shared_memory_fd;
+            info.sharedMemory = hidl_memory("audio_buffer", hidlHandle,
+                                            frameSize *halInfo.buffer_size_frames);
+            info.bufferSizeFrames = halInfo.buffer_size_frames;
+            info.burstSizeFrames = halInfo.burst_size_frames;
+        }
+    }
+    _hidl_cb(retval, info);
+    if (hidlHandle != nullptr) {
+        native_handle_close(hidlHandle);
+        native_handle_delete(hidlHandle);
+    }
+    return Void();
+}
+
+template <typename T>
+Return<void> StreamMmap<T>::getMmapPosition(IStream::getMmapPosition_cb _hidl_cb) {
+    Result retval(Result::NOT_SUPPORTED);
+    MmapPosition position;
+
+    if (mStream->get_mmap_position != NULL) {
+        struct audio_mmap_position halPosition;
+        retval = Stream::analyzeStatus(
+                "get_mmap_position",
+                mStream->get_mmap_position(mStream, &halPosition));
+        if (retval == Result::OK) {
+            position.timeNanoseconds = halPosition.time_nanoseconds;
+            position.positionFrames = halPosition.position_frames;
+        }
+    }
+    _hidl_cb(retval, position);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAM_H
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
new file mode 100644
index 0000000..ad18986
--- /dev/null
+++ b/audio/2.0/default/StreamIn.cpp
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "StreamInHAL"
+//#define LOG_NDEBUG 0
+
+#include <android/log.h>
+#include <hardware/audio.h>
+#include <mediautils/SchedulingPolicyService.h>
+
+#include "StreamIn.h"
+
+using ::android::hardware::audio::V2_0::MessageQueueFlagBits;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+namespace {
+
+class ReadThread : public Thread {
+  public:
+    // ReadThread's lifespan never exceeds StreamIn's lifespan.
+    ReadThread(std::atomic<bool>* stop,
+            audio_stream_in_t* stream,
+            StreamIn::DataMQ* dataMQ,
+            StreamIn::StatusMQ* statusMQ,
+            EventFlag* efGroup,
+            ThreadPriority threadPriority)
+            : Thread(false /*canCallJava*/),
+              mStop(stop),
+              mStream(stream),
+              mDataMQ(dataMQ),
+              mStatusMQ(statusMQ),
+              mEfGroup(efGroup),
+              mThreadPriority(threadPriority),
+              mBuffer(new uint8_t[dataMQ->getQuantumCount()]) {
+    }
+    virtual ~ReadThread() {}
+
+    status_t readyToRun() override;
+
+  private:
+    std::atomic<bool>* mStop;
+    audio_stream_in_t* mStream;
+    StreamIn::DataMQ* mDataMQ;
+    StreamIn::StatusMQ* mStatusMQ;
+    EventFlag* mEfGroup;
+    ThreadPriority mThreadPriority;
+    std::unique_ptr<uint8_t[]> mBuffer;
+
+    bool threadLoop() override;
+};
+
+status_t ReadThread::readyToRun() {
+    if (mThreadPriority != ThreadPriority::NORMAL) {
+        int err = requestPriority(
+                getpid(), getTid(), static_cast<int>(mThreadPriority), true /*asynchronous*/);
+        ALOGW_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
+                static_cast<int>(mThreadPriority), getpid(), getTid(), err);
+    }
+    return OK;
+}
+
+bool ReadThread::threadLoop() {
+    // This implementation doesn't return control back to the Thread until it decides to stop,
+    // as the Thread uses mutexes, and this can lead to priority inversion.
+    while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+        // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
+        uint32_t efState = 0;
+        mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState, NS_PER_SEC);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
+            continue;  // Nothing to do.
+        }
+
+        const size_t availToWrite = mDataMQ->availableToWrite();
+        ssize_t readResult = mStream->read(mStream, &mBuffer[0], availToWrite);
+        Result retval = Result::OK;
+        uint64_t read = 0;
+        if (readResult >= 0) {
+            read = readResult;
+            if (!mDataMQ->write(&mBuffer[0], readResult)) {
+                ALOGW("data message queue write failed");
+            }
+        } else {
+            retval = Stream::analyzeStatus("read", readResult);
+        }
+        IStreamIn::ReadStatus status = { retval, read };
+        if (!mStatusMQ->write(&status)) {
+            ALOGW("status message queue write failed");
+        }
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
+    }
+
+    return false;
+}
+
+}  // namespace
+
+StreamIn::StreamIn(audio_hw_device_t* device, audio_stream_in_t* stream)
+        : mIsClosed(false), mDevice(device), mStream(stream),
+          mStreamCommon(new Stream(&stream->common)),
+          mStreamMmap(new StreamMmap<audio_stream_in_t>(stream)),
+          mEfGroup(nullptr), mStopReadThread(false) {
+}
+
+StreamIn::~StreamIn() {
+    close();
+    mStream = nullptr;
+    mDevice = nullptr;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> StreamIn::getFrameSize()  {
+    return audio_stream_in_frame_size(mStream);
+}
+
+Return<uint64_t> StreamIn::getFrameCount()  {
+    return mStreamCommon->getFrameCount();
+}
+
+Return<uint64_t> StreamIn::getBufferSize()  {
+    return mStreamCommon->getBufferSize();
+}
+
+Return<uint32_t> StreamIn::getSampleRate()  {
+    return mStreamCommon->getSampleRate();
+}
+
+Return<void> StreamIn::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedSampleRates(_hidl_cb);
+}
+
+Return<Result> StreamIn::setSampleRate(uint32_t sampleRateHz)  {
+    return mStreamCommon->setSampleRate(sampleRateHz);
+}
+
+Return<AudioChannelMask> StreamIn::getChannelMask()  {
+    return mStreamCommon->getChannelMask();
+}
+
+Return<void> StreamIn::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
+
+Return<Result> StreamIn::setChannelMask(AudioChannelMask mask)  {
+    return mStreamCommon->setChannelMask(mask);
+}
+
+Return<AudioFormat> StreamIn::getFormat()  {
+    return mStreamCommon->getFormat();
+}
+
+Return<void> StreamIn::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedFormats(_hidl_cb);
+}
+
+Return<Result> StreamIn::setFormat(AudioFormat format)  {
+    return mStreamCommon->setFormat(format);
+}
+
+Return<void> StreamIn::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    return mStreamCommon->getAudioProperties(_hidl_cb);
+}
+
+Return<Result> StreamIn::addEffect(uint64_t effectId)  {
+    return mStreamCommon->addEffect(effectId);
+}
+
+Return<Result> StreamIn::removeEffect(uint64_t effectId)  {
+    return mStreamCommon->removeEffect(effectId);
+}
+
+Return<Result> StreamIn::standby()  {
+    return mStreamCommon->standby();
+}
+
+Return<AudioDevice> StreamIn::getDevice()  {
+    return mStreamCommon->getDevice();
+}
+
+Return<Result> StreamIn::setDevice(const DeviceAddress& address)  {
+    return mStreamCommon->setDevice(address);
+}
+
+Return<Result> StreamIn::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
+Return<Result> StreamIn::setHwAvSync(uint32_t hwAvSync)  {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+Return<void> StreamIn::getParameters(const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb) {
+    return mStreamCommon->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> StreamIn::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mStreamCommon->setParameters(parameters);
+}
+
+Return<void> StreamIn::debugDump(const hidl_handle& fd)  {
+    return mStreamCommon->debugDump(fd);
+}
+
+Return<Result> StreamIn::start() {
+    return mStreamMmap->start();
+}
+
+Return<Result> StreamIn::stop() {
+    return mStreamMmap->stop();
+}
+
+Return<void> StreamIn::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(
+            minSizeFrames, audio_stream_in_frame_size(mStream), _hidl_cb);
+}
+
+Return<void> StreamIn::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    return mStreamMmap->getMmapPosition(_hidl_cb);
+}
+
+Return<Result> StreamIn::close()  {
+    if (mIsClosed) return Result::INVALID_STATE;
+    mIsClosed = true;
+    if (mReadThread.get()) {
+        mStopReadThread.store(true, std::memory_order_release);
+        status_t status = mReadThread->requestExitAndWait();
+        ALOGE_IF(status, "read thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "read MQ event flag deletion error: %s", strerror(-status));
+    }
+    mDevice->close_input_stream(mDevice, mStream);
+    return Result::OK;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
+Return<void> StreamIn::getAudioSource(getAudioSource_cb _hidl_cb)  {
+    int halSource;
+    Result retval = mStreamCommon->getParam(AudioParameter::keyInputSource, &halSource);
+    AudioSource source(AudioSource::DEFAULT);
+    if (retval == Result::OK) {
+        source = AudioSource(halSource);
+    }
+    _hidl_cb(retval, source);
+    return Void();
+}
+
+Return<Result> StreamIn::setGain(float gain)  {
+    return Stream::analyzeStatus("set_gain", mStream->set_gain(mStream, gain));
+}
+
+Return<void> StreamIn::prepareForReading(
+        uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
+        prepareForReading_cb _hidl_cb)  {
+    status_t status;
+    // Create message queues.
+    if (mDataMQ) {
+        ALOGE("the client attempts to call prepareForReading twice");
+        _hidl_cb(Result::INVALID_STATE,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+    std::unique_ptr<DataMQ> tempDataMQ(
+            new DataMQ(frameSize * framesCount, true /* EventFlag */));
+    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
+    if (!tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
+        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+    // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
+    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+    if (status != OK || !mEfGroup) {
+        ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+
+    // Create and launch the thread.
+    mReadThread = new ReadThread(
+            &mStopReadThread,
+            mStream,
+            tempDataMQ.get(),
+            tempStatusMQ.get(),
+            mEfGroup,
+            threadPriority);
+    status = mReadThread->run("reader", PRIORITY_URGENT_AUDIO);
+    if (status != OK) {
+        ALOGW("failed to start reader thread: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+
+    mDataMQ = std::move(tempDataMQ);
+    mStatusMQ = std::move(tempStatusMQ);
+    _hidl_cb(Result::OK, *mDataMQ->getDesc(), *mStatusMQ->getDesc());
+    return Void();
+}
+
+Return<uint32_t> StreamIn::getInputFramesLost()  {
+    return mStream->get_input_frames_lost(mStream);
+}
+
+Return<void> StreamIn::getCapturePosition(getCapturePosition_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    uint64_t frames = 0, time = 0;
+    if (mStream->get_capture_position != NULL) {
+        int64_t halFrames, halTime;
+        retval = Stream::analyzeStatus(
+                "get_capture_position",
+                mStream->get_capture_position(mStream, &halFrames, &halTime),
+                // HAL may have a stub function, always returning ENOSYS, don't
+                // spam the log in this case.
+                ENOSYS);
+        if (retval == Result::OK) {
+            frames = halFrames;
+            time = halTime;
+        }
+    }
+    _hidl_cb(retval, frames, time);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamIn.h b/audio/2.0/default/StreamIn.h
new file mode 100644
index 0000000..fc813d9
--- /dev/null
+++ b/audio/2.0/default/StreamIn.h
@@ -0,0 +1,121 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
+
+#include <atomic>
+#include <memory>
+
+#include <android/hardware/audio/2.0/IStreamIn.h>
+#include <hidl/MQDescriptor.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
+
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::IStreamIn;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::audio::V2_0::ThreadPriority;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct StreamIn : public IStreamIn {
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<ReadStatus, kSynchronizedReadWrite> StatusMQ;
+
+    StreamIn(audio_hw_device_t* device, audio_stream_in_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IStreamIn follow.
+    Return<void> getAudioSource(getAudioSource_cb _hidl_cb)  override;
+    Return<Result> setGain(float gain)  override;
+    Return<void> prepareForReading(
+            uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
+            prepareForReading_cb _hidl_cb)  override;
+    Return<uint32_t> getInputFramesLost()  override;
+    Return<void> getCapturePosition(getCapturePosition_cb _hidl_cb)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+
+  private:
+    bool mIsClosed;
+    audio_hw_device_t *mDevice;
+    audio_stream_in_t *mStream;
+    sp<Stream> mStreamCommon;
+    sp<StreamMmap<audio_stream_in_t>> mStreamMmap;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopReadThread;
+    sp<Thread> mReadThread;
+
+    virtual ~StreamIn();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMIN_H
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
new file mode 100644
index 0000000..1948b68
--- /dev/null
+++ b/audio/2.0/default/StreamOut.cpp
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "StreamOutHAL"
+//#define LOG_NDEBUG 0
+
+#include <android/log.h>
+#include <hardware/audio.h>
+#include <mediautils/SchedulingPolicyService.h>
+
+#include "StreamOut.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+namespace {
+
+class WriteThread : public Thread {
+  public:
+    // WriteThread's lifespan never exceeds StreamOut's lifespan.
+    WriteThread(std::atomic<bool>* stop,
+            audio_stream_out_t* stream,
+            StreamOut::DataMQ* dataMQ,
+            StreamOut::StatusMQ* statusMQ,
+            EventFlag* efGroup,
+            ThreadPriority threadPriority)
+            : Thread(false /*canCallJava*/),
+              mStop(stop),
+              mStream(stream),
+              mDataMQ(dataMQ),
+              mStatusMQ(statusMQ),
+              mEfGroup(efGroup),
+              mThreadPriority(threadPriority),
+              mBuffer(new uint8_t[dataMQ->getQuantumCount()]) {
+    }
+    virtual ~WriteThread() {}
+
+    status_t readyToRun() override;
+
+  private:
+    std::atomic<bool>* mStop;
+    audio_stream_out_t* mStream;
+    StreamOut::DataMQ* mDataMQ;
+    StreamOut::StatusMQ* mStatusMQ;
+    EventFlag* mEfGroup;
+    ThreadPriority mThreadPriority;
+    std::unique_ptr<uint8_t[]> mBuffer;
+
+    bool threadLoop() override;
+};
+
+status_t WriteThread::readyToRun() {
+    if (mThreadPriority != ThreadPriority::NORMAL) {
+        int err = requestPriority(
+                getpid(), getTid(), static_cast<int>(mThreadPriority), true /*asynchronous*/);
+        ALOGW_IF(err, "failed to set priority %d for pid %d tid %d; error %d",
+                static_cast<int>(mThreadPriority), getpid(), getTid(), err);
+    }
+    return OK;
+}
+
+bool WriteThread::threadLoop() {
+    // This implementation doesn't return control back to the Thread until it decides to stop,
+    // as the Thread uses mutexes, and this can lead to priority inversion.
+    while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+        // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
+        uint32_t efState = 0;
+        mEfGroup->wait(
+                static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState, NS_PER_SEC);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
+            continue;  // Nothing to do.
+        }
+
+        const size_t availToRead = mDataMQ->availableToRead();
+        IStreamOut::WriteStatus status;
+        status.writeRetval = Result::OK;
+        status.written = 0;
+        if (mDataMQ->read(&mBuffer[0], availToRead)) {
+            ssize_t writeResult = mStream->write(mStream, &mBuffer[0], availToRead);
+            if (writeResult >= 0) {
+                status.written = writeResult;
+            } else {
+                status.writeRetval = Stream::analyzeStatus("write", writeResult);
+            }
+        }
+        status.presentationPositionRetval = status.writeRetval == Result::OK ?
+                StreamOut::getPresentationPositionImpl(mStream, &status.frames, &status.timeStamp) :
+                Result::OK;
+        if (!mStatusMQ->write(&status)) {
+            ALOGW("status message queue write failed");
+        }
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL));
+    }
+
+    return false;
+}
+
+}  // namespace
+
+StreamOut::StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream)
+        : mIsClosed(false), mDevice(device), mStream(stream),
+          mStreamCommon(new Stream(&stream->common)),
+          mStreamMmap(new StreamMmap<audio_stream_out_t>(stream)),
+          mEfGroup(nullptr), mStopWriteThread(false) {
+}
+
+StreamOut::~StreamOut() {
+    close();
+    mStream = nullptr;
+    mDevice = nullptr;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStream follow.
+Return<uint64_t> StreamOut::getFrameSize()  {
+    return audio_stream_out_frame_size(mStream);
+}
+
+Return<uint64_t> StreamOut::getFrameCount()  {
+    return mStreamCommon->getFrameCount();
+}
+
+Return<uint64_t> StreamOut::getBufferSize()  {
+    return mStreamCommon->getBufferSize();
+}
+
+Return<uint32_t> StreamOut::getSampleRate()  {
+    return mStreamCommon->getSampleRate();
+}
+
+Return<void> StreamOut::getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedSampleRates(_hidl_cb);
+}
+
+Return<Result> StreamOut::setSampleRate(uint32_t sampleRateHz)  {
+    return mStreamCommon->setSampleRate(sampleRateHz);
+}
+
+Return<AudioChannelMask> StreamOut::getChannelMask()  {
+    return mStreamCommon->getChannelMask();
+}
+
+Return<void> StreamOut::getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedChannelMasks(_hidl_cb);
+}
+
+Return<Result> StreamOut::setChannelMask(AudioChannelMask mask)  {
+    return mStreamCommon->setChannelMask(mask);
+}
+
+Return<AudioFormat> StreamOut::getFormat()  {
+    return mStreamCommon->getFormat();
+}
+
+Return<void> StreamOut::getSupportedFormats(getSupportedFormats_cb _hidl_cb)  {
+    return mStreamCommon->getSupportedFormats(_hidl_cb);
+}
+
+Return<Result> StreamOut::setFormat(AudioFormat format)  {
+    return mStreamCommon->setFormat(format);
+}
+
+Return<void> StreamOut::getAudioProperties(getAudioProperties_cb _hidl_cb)  {
+    return mStreamCommon->getAudioProperties(_hidl_cb);
+}
+
+Return<Result> StreamOut::addEffect(uint64_t effectId)  {
+    return mStreamCommon->addEffect(effectId);
+}
+
+Return<Result> StreamOut::removeEffect(uint64_t effectId)  {
+    return mStreamCommon->removeEffect(effectId);
+}
+
+Return<Result> StreamOut::standby()  {
+    return mStreamCommon->standby();
+}
+
+Return<AudioDevice> StreamOut::getDevice()  {
+    return mStreamCommon->getDevice();
+}
+
+Return<Result> StreamOut::setDevice(const DeviceAddress& address)  {
+    return mStreamCommon->setDevice(address);
+}
+
+Return<Result> StreamOut::setConnectedState(const DeviceAddress& address, bool connected)  {
+    return mStreamCommon->setConnectedState(address, connected);
+}
+
+Return<Result> StreamOut::setHwAvSync(uint32_t hwAvSync)  {
+    return mStreamCommon->setHwAvSync(hwAvSync);
+}
+
+Return<void> StreamOut::getParameters(
+        const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  {
+    return mStreamCommon->getParameters(keys, _hidl_cb);
+}
+
+Return<Result> StreamOut::setParameters(const hidl_vec<ParameterValue>& parameters)  {
+    return mStreamCommon->setParameters(parameters);
+}
+
+Return<void> StreamOut::debugDump(const hidl_handle& fd)  {
+    return mStreamCommon->debugDump(fd);
+}
+
+Return<Result> StreamOut::close()  {
+    if (mIsClosed) return Result::INVALID_STATE;
+    mIsClosed = true;
+    if (mWriteThread.get()) {
+        mStopWriteThread.store(true, std::memory_order_release);
+        status_t status = mWriteThread->requestExitAndWait();
+        ALOGE_IF(status, "write thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "write MQ event flag deletion error: %s", strerror(-status));
+    }
+    mCallback.clear();
+    mDevice->close_output_stream(mDevice, mStream);
+    return Result::OK;
+}
+
+// Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
+Return<uint32_t> StreamOut::getLatency()  {
+    return mStream->get_latency(mStream);
+}
+
+Return<Result> StreamOut::setVolume(float left, float right)  {
+    Result retval(Result::NOT_SUPPORTED);
+    if (mStream->set_volume != NULL) {
+        retval = Stream::analyzeStatus(
+                "set_volume", mStream->set_volume(mStream, left, right));
+    }
+    return retval;
+}
+
+Return<void> StreamOut::prepareForWriting(
+        uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
+        prepareForWriting_cb _hidl_cb)  {
+    status_t status;
+    // Create message queues.
+    if (mDataMQ) {
+        ALOGE("the client attempts to call prepareForWriting twice");
+        _hidl_cb(Result::INVALID_STATE,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+    std::unique_ptr<DataMQ> tempDataMQ(
+            new DataMQ(frameSize * framesCount, true /* EventFlag */));
+    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1));
+    if (!tempDataMQ->isValid() || !tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempDataMQ->isValid(), "data MQ is invalid");
+        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+    // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
+    status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
+    if (status != OK || !mEfGroup) {
+        ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+
+    // Create and launch the thread.
+    mWriteThread = new WriteThread(
+            &mStopWriteThread,
+            mStream,
+            tempDataMQ.get(),
+            tempStatusMQ.get(),
+            mEfGroup,
+            threadPriority);
+    status = mWriteThread->run("writer", PRIORITY_URGENT_AUDIO);
+    if (status != OK) {
+        ALOGW("failed to start writer thread: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS,
+                DataMQ::Descriptor(), StatusMQ::Descriptor());
+        return Void();
+    }
+
+    mDataMQ = std::move(tempDataMQ);
+    mStatusMQ = std::move(tempStatusMQ);
+    _hidl_cb(Result::OK, *mDataMQ->getDesc(), *mStatusMQ->getDesc());
+    return Void();
+}
+
+Return<void> StreamOut::getRenderPosition(getRenderPosition_cb _hidl_cb)  {
+    uint32_t halDspFrames;
+    Result retval = Stream::analyzeStatus(
+            "get_render_position", mStream->get_render_position(mStream, &halDspFrames));
+    _hidl_cb(retval, halDspFrames);
+    return Void();
+}
+
+Return<void> StreamOut::getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb)  {
+    Result retval(Result::NOT_SUPPORTED);
+    int64_t timestampUs = 0;
+    if (mStream->get_next_write_timestamp != NULL) {
+        retval = Stream::analyzeStatus(
+                "get_next_write_timestamp",
+                mStream->get_next_write_timestamp(mStream, &timestampUs));
+    }
+    _hidl_cb(retval, timestampUs);
+    return Void();
+}
+
+Return<Result> StreamOut::setCallback(const sp<IStreamOutCallback>& callback)  {
+    if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
+    int result = mStream->set_callback(mStream, StreamOut::asyncCallback, this);
+    if (result == 0) {
+        mCallback = callback;
+    }
+    return Stream::analyzeStatus("set_callback", result);
+}
+
+Return<Result> StreamOut::clearCallback()  {
+    if (mStream->set_callback == NULL) return Result::NOT_SUPPORTED;
+    mCallback.clear();
+    return Result::OK;
+}
+
+// static
+int StreamOut::asyncCallback(stream_callback_event_t event, void*, void *cookie) {
+    wp<StreamOut> weakSelf(reinterpret_cast<StreamOut*>(cookie));
+    sp<StreamOut> self = weakSelf.promote();
+    if (self == nullptr || self->mCallback == nullptr) return 0;
+    ALOGV("asyncCallback() event %d", event);
+    switch (event) {
+        case STREAM_CBK_EVENT_WRITE_READY:
+            self->mCallback->onWriteReady();
+            break;
+        case STREAM_CBK_EVENT_DRAIN_READY:
+            self->mCallback->onDrainReady();
+            break;
+        case STREAM_CBK_EVENT_ERROR:
+            self->mCallback->onError();
+            break;
+        default:
+            ALOGW("asyncCallback() unknown event %d", event);
+            break;
+    }
+    return 0;
+}
+
+Return<void> StreamOut::supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb)  {
+    _hidl_cb(mStream->pause != NULL, mStream->resume != NULL);
+    return Void();
+}
+
+Return<Result> StreamOut::pause()  {
+    return mStream->pause != NULL ?
+            Stream::analyzeStatus("pause", mStream->pause(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<Result> StreamOut::resume()  {
+    return mStream->resume != NULL ?
+            Stream::analyzeStatus("resume", mStream->resume(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<bool> StreamOut::supportsDrain()  {
+    return mStream->drain != NULL;
+}
+
+Return<Result> StreamOut::drain(AudioDrain type)  {
+    return mStream->drain != NULL ?
+            Stream::analyzeStatus(
+                    "drain", mStream->drain(mStream, static_cast<audio_drain_type_t>(type))) :
+            Result::NOT_SUPPORTED;
+}
+
+Return<Result> StreamOut::flush()  {
+    return mStream->flush != NULL ?
+            Stream::analyzeStatus("flush", mStream->flush(mStream)) :
+            Result::NOT_SUPPORTED;
+}
+
+// static
+Result StreamOut::getPresentationPositionImpl(
+        audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp) {
+    Result retval(Result::NOT_SUPPORTED);
+    if (stream->get_presentation_position == NULL) return retval;
+    struct timespec halTimeStamp;
+    retval = Stream::analyzeStatus(
+            "get_presentation_position",
+            stream->get_presentation_position(stream, frames, &halTimeStamp),
+            // Don't logspam on EINVAL--it's normal for get_presentation_position
+            // to return it sometimes.
+            EINVAL);
+    if (retval == Result::OK) {
+        timeStamp->tvSec = halTimeStamp.tv_sec;
+        timeStamp->tvNSec = halTimeStamp.tv_nsec;
+    }
+    return retval;
+}
+
+Return<void> StreamOut::getPresentationPosition(getPresentationPosition_cb _hidl_cb)  {
+    uint64_t frames = 0;
+    TimeSpec timeStamp = { 0, 0 };
+    Result retval = getPresentationPositionImpl(mStream, &frames, &timeStamp);
+    _hidl_cb(retval, frames, timeStamp);
+    return Void();
+}
+
+Return<Result> StreamOut::start() {
+    return mStreamMmap->start();
+}
+
+Return<Result> StreamOut::stop() {
+    return mStreamMmap->stop();
+}
+
+Return<void> StreamOut::createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) {
+    return mStreamMmap->createMmapBuffer(
+            minSizeFrames, audio_stream_out_frame_size(mStream), _hidl_cb);
+}
+
+Return<void> StreamOut::getMmapPosition(getMmapPosition_cb _hidl_cb) {
+    return mStreamMmap->getMmapPosition(_hidl_cb);
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/2.0/default/StreamOut.h b/audio/2.0/default/StreamOut.h
new file mode 100644
index 0000000..754a0c0
--- /dev/null
+++ b/audio/2.0/default/StreamOut.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
+#define ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
+
+#include <atomic>
+#include <memory>
+
+#include <android/hardware/audio/2.0/IStreamOut.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <utils/Thread.h>
+
+#include "Stream.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::V2_0::AudioDrain;
+using ::android::hardware::audio::V2_0::DeviceAddress;
+using ::android::hardware::audio::V2_0::IStream;
+using ::android::hardware::audio::V2_0::IStreamOut;
+using ::android::hardware::audio::V2_0::IStreamOutCallback;
+using ::android::hardware::audio::V2_0::ParameterValue;
+using ::android::hardware::audio::V2_0::Result;
+using ::android::hardware::audio::V2_0::ThreadPriority;
+using ::android::hardware::audio::V2_0::TimeSpec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct StreamOut : public IStreamOut {
+    typedef MessageQueue<uint8_t, kSynchronizedReadWrite> DataMQ;
+    typedef MessageQueue<WriteStatus, kSynchronizedReadWrite> StatusMQ;
+
+    StreamOut(audio_hw_device_t* device, audio_stream_out_t* stream);
+
+    // Methods from ::android::hardware::audio::V2_0::IStream follow.
+    Return<uint64_t> getFrameSize()  override;
+    Return<uint64_t> getFrameCount()  override;
+    Return<uint64_t> getBufferSize()  override;
+    Return<uint32_t> getSampleRate()  override;
+    Return<void> getSupportedSampleRates(getSupportedSampleRates_cb _hidl_cb)  override;
+    Return<Result> setSampleRate(uint32_t sampleRateHz)  override;
+    Return<AudioChannelMask> getChannelMask()  override;
+    Return<void> getSupportedChannelMasks(getSupportedChannelMasks_cb _hidl_cb)  override;
+    Return<Result> setChannelMask(AudioChannelMask mask)  override;
+    Return<AudioFormat> getFormat()  override;
+    Return<void> getSupportedFormats(getSupportedFormats_cb _hidl_cb)  override;
+    Return<Result> setFormat(AudioFormat format)  override;
+    Return<void> getAudioProperties(getAudioProperties_cb _hidl_cb)  override;
+    Return<Result> addEffect(uint64_t effectId)  override;
+    Return<Result> removeEffect(uint64_t effectId)  override;
+    Return<Result> standby()  override;
+    Return<AudioDevice> getDevice()  override;
+    Return<Result> setDevice(const DeviceAddress& address)  override;
+    Return<Result> setConnectedState(const DeviceAddress& address, bool connected)  override;
+    Return<Result> setHwAvSync(uint32_t hwAvSync)  override;
+    Return<void> getParameters(
+            const hidl_vec<hidl_string>& keys, getParameters_cb _hidl_cb)  override;
+    Return<Result> setParameters(const hidl_vec<ParameterValue>& parameters)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::V2_0::IStreamOut follow.
+    Return<uint32_t> getLatency()  override;
+    Return<Result> setVolume(float left, float right)  override;
+    Return<void> prepareForWriting(
+            uint32_t frameSize, uint32_t framesCount, ThreadPriority threadPriority,
+            prepareForWriting_cb _hidl_cb)  override;
+    Return<void> getRenderPosition(getRenderPosition_cb _hidl_cb)  override;
+    Return<void> getNextWriteTimestamp(getNextWriteTimestamp_cb _hidl_cb)  override;
+    Return<Result> setCallback(const sp<IStreamOutCallback>& callback)  override;
+    Return<Result> clearCallback()  override;
+    Return<void> supportsPauseAndResume(supportsPauseAndResume_cb _hidl_cb)  override;
+    Return<Result> pause()  override;
+    Return<Result> resume()  override;
+    Return<bool> supportsDrain()  override;
+    Return<Result> drain(AudioDrain type)  override;
+    Return<Result> flush()  override;
+    Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb)  override;
+    Return<Result> start() override;
+    Return<Result> stop() override;
+    Return<void> createMmapBuffer(int32_t minSizeFrames, createMmapBuffer_cb _hidl_cb) override;
+    Return<void> getMmapPosition(getMmapPosition_cb _hidl_cb) override;
+
+    static Result getPresentationPositionImpl(
+            audio_stream_out_t *stream, uint64_t *frames, TimeSpec *timeStamp);
+
+  private:
+    bool mIsClosed;
+    audio_hw_device_t *mDevice;
+    audio_stream_out_t *mStream;
+    sp<Stream> mStreamCommon;
+    sp<StreamMmap<audio_stream_out_t>> mStreamMmap;
+    sp<IStreamOutCallback> mCallback;
+    std::unique_ptr<DataMQ> mDataMQ;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopWriteThread;
+    sp<Thread> mWriteThread;
+
+    virtual ~StreamOut();
+
+    static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_V2_0_STREAMOUT_H
diff --git a/audio/2.0/default/android.hardware.audio@2.0-service.rc b/audio/2.0/default/android.hardware.audio@2.0-service.rc
new file mode 100644
index 0000000..0a5bfc5
--- /dev/null
+++ b/audio/2.0/default/android.hardware.audio@2.0-service.rc
@@ -0,0 +1,11 @@
+service audio-hal-2-0 /system/bin/hw/android.hardware.audio@2.0-service
+    class hal
+    user audioserver
+    # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
+    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
+    # audioflinger restarts itself when it loses connection with the hal
+    # and its .rc file has an "onrestart restart audio-hal" rule, thus
+    # an additional auto-restart from the init process isn't needed.
+    oneshot
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
new file mode 100644
index 0000000..646d898
--- /dev/null
+++ b/audio/2.0/default/service.cpp
@@ -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.
+ */
+
+#define LOG_TAG "audiohalservice"
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+#include <android/hardware/audio/2.0/IDevicesFactory.h>
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+
+using android::hardware::audio::effect::V2_0::IEffectsFactory;
+using android::hardware::audio::V2_0::IDevicesFactory;
+using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using android::hardware::registerPassthroughServiceImplementation;
+using android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
+
+int main(int /* argc */, char* /* argv */ []) {
+    configureRpcThreadpool(16, true /*callerWillJoin*/);
+    registerPassthroughServiceImplementation<IDevicesFactory>("audio_devices_factory");
+    registerPassthroughServiceImplementation<IEffectsFactory>("audio_effects_factory");
+    registerPassthroughServiceImplementation<ISoundTriggerHw>("sound_trigger.primary");
+    registerPassthroughServiceImplementation<IBroadcastRadioFactory>("broadcastradio");
+    joinRpcThreadpool();
+}
diff --git a/audio/2.0/types.hal b/audio/2.0/types.hal
new file mode 100644
index 0000000..8fc4314
--- /dev/null
+++ b/audio/2.0/types.hal
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio@2.0;
+
+import android.hardware.audio.common@2.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
+};
+
+/*
+ * Mmap buffer descriptor returned by IStream.createMmapBuffer().
+ * Used by streams opened in mmap mode.
+ */
+struct MmapBufferInfo {
+    memory  sharedMemory;         // mmap memory buffer
+    int32_t bufferSizeFrames;     // total buffer size in frames
+    int32_t burstSizeFrames;      // transfer size granularity in frames
+};
+
+/*
+ * 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
+};
+
+/*
+ * The priority of threads executing reads and writes of audio data.
+ */
+enum ThreadPriority : int32_t {
+    NORMAL = 0,
+    FAST_CAPTURE = 3,
+    FAST_MIXER = 3
+};
diff --git a/audio/Android.bp b/audio/Android.bp
new file mode 100644
index 0000000..3121a36
--- /dev/null
+++ b/audio/Android.bp
@@ -0,0 +1,7 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "2.0",
+    "common/2.0",
+    "effect/2.0",
+    "effect/2.0/vts/functional",
+]
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
new file mode 100644
index 0000000..5d33733
--- /dev/null
+++ b/audio/common/2.0/Android.bp
@@ -0,0 +1,46 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.audio.common@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio.common@2.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/audio/common/2.0/types.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.audio.common@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio.common@2.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/audio/common/2.0/types.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.common@2.0",
+    generated_sources: ["android.hardware.audio.common@2.0_genc++"],
+    generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/audio/common/2.0/Android.mk b/audio/common/2.0/Android.mk
new file mode 100644
index 0000000..423fe35
--- /dev/null
+++ b/audio/common/2.0/Android.mk
@@ -0,0 +1,39 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio.common@2.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/audio/common/V2_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.audio.common@2.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/audio/common/2.0/default/Android.mk b/audio/common/2.0/default/Android.mk
new file mode 100644
index 0000000..8e2fed4
--- /dev/null
+++ b/audio/common/2.0/default/Android.mk
@@ -0,0 +1,32 @@
+#
+# 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.
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio.common@2.0-util
+LOCAL_SRC_FILES := \
+    EffectMap.cpp \
+    HidlUtils.cpp \
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+LOCAL_SHARED_LIBRARIES := \
+    libutils \
+    libhidlbase \
+    android.hardware.audio.common@2.0 \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/common/2.0/default/EffectMap.cpp b/audio/common/2.0/default/EffectMap.cpp
new file mode 100644
index 0000000..703b91c
--- /dev/null
+++ b/audio/common/2.0/default/EffectMap.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#include <atomic>
+
+#include "EffectMap.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(EffectMap);
+
+// static
+const uint64_t EffectMap::INVALID_ID = 0;
+
+// static
+uint64_t EffectMap::makeUniqueId() {
+    static std::atomic<uint64_t> counter{INVALID_ID + 1};
+    return counter++;
+}
+
+uint64_t EffectMap::add(effect_handle_t handle) {
+    uint64_t newId = makeUniqueId();
+    std::lock_guard<std::mutex> lock(mLock);
+    mEffects.add(newId, handle);
+    return newId;
+}
+
+effect_handle_t EffectMap::get(const uint64_t& id) {
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mEffects.indexOfKey(id);
+    return idx >= 0 ? mEffects[idx] : NULL;
+}
+
+void EffectMap::remove(effect_handle_t handle) {
+    std::lock_guard<std::mutex> lock(mLock);
+    for (size_t i = 0; i < mEffects.size(); ++i) {
+        if (mEffects[i] == handle) {
+            mEffects.removeItemsAt(i);
+            break;
+        }
+    }
+}
+
+}  // namespace android
diff --git a/audio/common/2.0/default/EffectMap.h b/audio/common/2.0/default/EffectMap.h
new file mode 100644
index 0000000..82bbb1f
--- /dev/null
+++ b/audio/common/2.0/default/EffectMap.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_V2_0_EffectMap_H_
+#define android_hardware_audio_V2_0_EffectMap_H_
+
+#include <mutex>
+
+#include <hardware/audio_effect.h>
+#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
+
+namespace android {
+
+// This class needs to be in 'android' ns because Singleton macros require that.
+class EffectMap : public Singleton<EffectMap> {
+  public:
+    static const uint64_t INVALID_ID;
+
+    uint64_t add(effect_handle_t handle);
+    effect_handle_t get(const uint64_t& id);
+    void remove(effect_handle_t handle);
+
+  private:
+    static uint64_t makeUniqueId();
+
+    std::mutex mLock;
+    KeyedVector<uint64_t, effect_handle_t> mEffects;
+};
+
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_EffectMap_H_
diff --git a/audio/common/2.0/default/HidlUtils.cpp b/audio/common/2.0/default/HidlUtils.cpp
new file mode 100644
index 0000000..241ca90
--- /dev/null
+++ b/audio/common/2.0/default/HidlUtils.cpp
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#include <string.h>
+
+#include "HidlUtils.h"
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::common::V2_0::AudioGainMode;
+using ::android::hardware::audio::common::V2_0::AudioMixLatencyClass;
+using ::android::hardware::audio::common::V2_0::AudioPortConfigMask;
+using ::android::hardware::audio::common::V2_0::AudioPortRole;
+using ::android::hardware::audio::common::V2_0::AudioPortType;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::common::V2_0::AudioStreamType;
+
+namespace android {
+
+void HidlUtils::audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config) {
+    config->sampleRateHz = halConfig.sample_rate;
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->format = AudioFormat(halConfig.format);
+    audioOffloadInfoFromHal(halConfig.offload_info, &config->offloadInfo);
+    config->frameCount = halConfig.frame_count;
+}
+
+void HidlUtils::audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig) {
+    memset(halConfig, 0, sizeof(audio_config_t));
+    halConfig->sample_rate = config.sampleRateHz;
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    halConfig->format = static_cast<audio_format_t>(config.format);
+    audioOffloadInfoToHal(config.offloadInfo, &halConfig->offload_info);
+    halConfig->frame_count = config.frameCount;
+}
+
+void HidlUtils::audioGainConfigFromHal(
+        const struct audio_gain_config& halConfig, AudioGainConfig* config) {
+    config->index = halConfig.index;
+    config->mode = AudioGainMode(halConfig.mode);
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
+        config->values[i] = halConfig.values[i];
+    }
+    config->rampDurationMs = halConfig.ramp_duration_ms;
+}
+
+void HidlUtils::audioGainConfigToHal(
+        const AudioGainConfig& config, struct audio_gain_config* halConfig) {
+    halConfig->index = config.index;
+    halConfig->mode = static_cast<audio_gain_mode_t>(config.mode);
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    memset(halConfig->values, 0, sizeof(halConfig->values));
+    for (size_t i = 0; i < sizeof(audio_channel_mask_t) * 8; ++i) {
+        halConfig->values[i] = config.values[i];
+    }
+    halConfig->ramp_duration_ms = config.rampDurationMs;
+}
+
+void HidlUtils::audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain) {
+    gain->mode = AudioGainMode(halGain.mode);
+    gain->channelMask = AudioChannelMask(halGain.channel_mask);
+    gain->minValue = halGain.min_value;
+    gain->maxValue = halGain.max_value;
+    gain->defaultValue = halGain.default_value;
+    gain->stepValue = halGain.step_value;
+    gain->minRampMs = halGain.min_ramp_ms;
+    gain->maxRampMs = halGain.max_ramp_ms;
+}
+
+void HidlUtils::audioGainToHal(const AudioGain& gain, struct audio_gain* halGain) {
+    halGain->mode = static_cast<audio_gain_mode_t>(gain.mode);
+    halGain->channel_mask = static_cast<audio_channel_mask_t>(gain.channelMask);
+    halGain->min_value = gain.minValue;
+    halGain->max_value = gain.maxValue;
+    halGain->default_value = gain.defaultValue;
+    halGain->step_value = gain.stepValue;
+    halGain->min_ramp_ms = gain.minRampMs;
+    halGain->max_ramp_ms = gain.maxRampMs;
+}
+
+void HidlUtils::audioOffloadInfoFromHal(
+        const audio_offload_info_t& halOffload, AudioOffloadInfo* offload) {
+    offload->sampleRateHz = halOffload.sample_rate;
+    offload->channelMask = AudioChannelMask(halOffload.channel_mask);
+    offload->format = AudioFormat(halOffload.format);
+    offload->streamType = AudioStreamType(halOffload.stream_type);
+    offload->bitRatePerSecond = halOffload.bit_rate;
+    offload->durationMicroseconds = halOffload.duration_us;
+    offload->hasVideo = halOffload.has_video;
+    offload->isStreaming = halOffload.is_streaming;
+}
+
+void HidlUtils::audioOffloadInfoToHal(
+        const AudioOffloadInfo& offload, audio_offload_info_t* halOffload) {
+    *halOffload = AUDIO_INFO_INITIALIZER;
+    halOffload->sample_rate = offload.sampleRateHz;
+    halOffload->channel_mask = static_cast<audio_channel_mask_t>(offload.channelMask);
+    halOffload->format = static_cast<audio_format_t>(offload.format);
+    halOffload->stream_type = static_cast<audio_stream_type_t>(offload.streamType);
+    halOffload->bit_rate = offload.bitRatePerSecond;
+    halOffload->duration_us = offload.durationMicroseconds;
+    halOffload->has_video = offload.hasVideo;
+    halOffload->is_streaming = offload.isStreaming;
+    halOffload->bit_width = offload.bitWidth;
+    halOffload->offload_buffer_size = offload.bufferSize;
+    halOffload->usage = static_cast<audio_usage_t>(offload.usage);
+}
+
+void HidlUtils::audioPortConfigFromHal(
+        const struct audio_port_config& halConfig, AudioPortConfig* config) {
+    config->id = halConfig.id;
+    config->role = AudioPortRole(halConfig.role);
+    config->type = AudioPortType(halConfig.type);
+    config->configMask = AudioPortConfigMask(halConfig.config_mask);
+    config->sampleRateHz = halConfig.sample_rate;
+    config->channelMask = AudioChannelMask(halConfig.channel_mask);
+    config->format = AudioFormat(halConfig.format);
+    audioGainConfigFromHal(halConfig.gain, &config->gain);
+    switch (halConfig.type) {
+        case AUDIO_PORT_TYPE_NONE: break;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            config->ext.device.hwModule = halConfig.ext.device.hw_module;
+            config->ext.device.type = AudioDevice(halConfig.ext.device.type);
+            memcpy(config->ext.device.address.data(),
+                    halConfig.ext.device.address,
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            config->ext.mix.hwModule = halConfig.ext.mix.hw_module;
+            config->ext.mix.ioHandle = halConfig.ext.mix.handle;
+            if (halConfig.role == AUDIO_PORT_ROLE_SOURCE) {
+                config->ext.mix.useCase.source = AudioSource(halConfig.ext.mix.usecase.source);
+            } else if (halConfig.role == AUDIO_PORT_ROLE_SINK) {
+                config->ext.mix.useCase.stream = AudioStreamType(halConfig.ext.mix.usecase.stream);
+            }
+            break;
+        }
+        case AUDIO_PORT_TYPE_SESSION: {
+            config->ext.session.session = halConfig.ext.session.session;
+            break;
+        }
+    }
+}
+
+void HidlUtils::audioPortConfigToHal(
+        const AudioPortConfig& config, struct audio_port_config* halConfig) {
+    memset(halConfig, 0, sizeof(audio_port_config));
+    halConfig->id = config.id;
+    halConfig->role = static_cast<audio_port_role_t>(config.role);
+    halConfig->type = static_cast<audio_port_type_t>(config.type);
+    halConfig->config_mask = static_cast<unsigned int>(config.configMask);
+    halConfig->sample_rate = config.sampleRateHz;
+    halConfig->channel_mask = static_cast<audio_channel_mask_t>(config.channelMask);
+    halConfig->format = static_cast<audio_format_t>(config.format);
+    audioGainConfigToHal(config.gain, &halConfig->gain);
+    switch (config.type) {
+        case AudioPortType::NONE: break;
+        case AudioPortType::DEVICE: {
+            halConfig->ext.device.hw_module = config.ext.device.hwModule;
+            halConfig->ext.device.type = static_cast<audio_devices_t>(config.ext.device.type);
+            memcpy(halConfig->ext.device.address,
+                    config.ext.device.address.data(),
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AudioPortType::MIX: {
+            halConfig->ext.mix.hw_module = config.ext.mix.hwModule;
+            halConfig->ext.mix.handle = config.ext.mix.ioHandle;
+            if (config.role == AudioPortRole::SOURCE) {
+                halConfig->ext.mix.usecase.source =
+                        static_cast<audio_source_t>(config.ext.mix.useCase.source);
+            } else if (config.role == AudioPortRole::SINK) {
+                halConfig->ext.mix.usecase.stream =
+                        static_cast<audio_stream_type_t>(config.ext.mix.useCase.stream);
+            }
+            break;
+        }
+        case AudioPortType::SESSION: {
+            halConfig->ext.session.session =
+                    static_cast<audio_session_t>(config.ext.session.session);
+            break;
+        }
+    }
+}
+
+void HidlUtils::audioPortConfigsFromHal(
+        unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
+        hidl_vec<AudioPortConfig> *configs) {
+    configs->resize(numHalConfigs);
+    for (unsigned int i = 0; i < numHalConfigs; ++i) {
+        audioPortConfigFromHal(halConfigs[i], &(*configs)[i]);
+    }
+}
+
+std::unique_ptr<audio_port_config[]> HidlUtils::audioPortConfigsToHal(
+        const hidl_vec<AudioPortConfig>& configs) {
+    std::unique_ptr<audio_port_config[]> halConfigs(new audio_port_config[configs.size()]);
+    for (size_t i = 0; i < configs.size(); ++i) {
+        audioPortConfigToHal(configs[i], &halConfigs[i]);
+    }
+    return halConfigs;
+}
+
+void HidlUtils::audioPortFromHal(const struct audio_port& halPort, AudioPort* port) {
+    port->id = halPort.id;
+    port->role = AudioPortRole(halPort.role);
+    port->type = AudioPortType(halPort.type);
+    port->name.setToExternal(halPort.name, strlen(halPort.name));
+    port->sampleRates.resize(halPort.num_sample_rates);
+    for (size_t i = 0; i < halPort.num_sample_rates; ++i) {
+        port->sampleRates[i] = halPort.sample_rates[i];
+    }
+    port->channelMasks.resize(halPort.num_channel_masks);
+    for (size_t i = 0; i < halPort.num_channel_masks; ++i) {
+        port->channelMasks[i] = AudioChannelMask(halPort.channel_masks[i]);
+    }
+    port->formats.resize(halPort.num_formats);
+    for (size_t i = 0; i < halPort.num_formats; ++i) {
+        port->formats[i] = AudioFormat(halPort.formats[i]);
+    }
+    port->gains.resize(halPort.num_gains);
+    for (size_t i = 0; i < halPort.num_gains; ++i) {
+        audioGainFromHal(halPort.gains[i], &port->gains[i]);
+    }
+    audioPortConfigFromHal(halPort.active_config, &port->activeConfig);
+    switch (halPort.type) {
+        case AUDIO_PORT_TYPE_NONE: break;
+        case AUDIO_PORT_TYPE_DEVICE: {
+            port->ext.device.hwModule = halPort.ext.device.hw_module;
+            port->ext.device.type = AudioDevice(halPort.ext.device.type);
+            memcpy(port->ext.device.address.data(),
+                    halPort.ext.device.address,
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AUDIO_PORT_TYPE_MIX: {
+            port->ext.mix.hwModule = halPort.ext.mix.hw_module;
+            port->ext.mix.ioHandle = halPort.ext.mix.handle;
+            port->ext.mix.latencyClass = AudioMixLatencyClass(halPort.ext.mix.latency_class);
+            break;
+        }
+        case AUDIO_PORT_TYPE_SESSION: {
+            port->ext.session.session = halPort.ext.session.session;
+            break;
+        }
+    }
+}
+
+void HidlUtils::audioPortToHal(const AudioPort& port, struct audio_port* halPort) {
+    memset(halPort, 0, sizeof(audio_port));
+    halPort->id = port.id;
+    halPort->role = static_cast<audio_port_role_t>(port.role);
+    halPort->type = static_cast<audio_port_type_t>(port.type);
+    memcpy(halPort->name,
+            port.name.c_str(),
+            std::min(port.name.size(), static_cast<size_t>(AUDIO_PORT_MAX_NAME_LEN)));
+    halPort->num_sample_rates =
+            std::min(port.sampleRates.size(), static_cast<size_t>(AUDIO_PORT_MAX_SAMPLING_RATES));
+    for (size_t i = 0; i < halPort->num_sample_rates; ++i) {
+        halPort->sample_rates[i] = port.sampleRates[i];
+    }
+    halPort->num_channel_masks =
+            std::min(port.channelMasks.size(), static_cast<size_t>(AUDIO_PORT_MAX_CHANNEL_MASKS));
+    for (size_t i = 0; i < halPort->num_channel_masks; ++i) {
+        halPort->channel_masks[i] = static_cast<audio_channel_mask_t>(port.channelMasks[i]);
+    }
+    halPort->num_formats =
+            std::min(port.formats.size(), static_cast<size_t>(AUDIO_PORT_MAX_FORMATS));
+    for (size_t i = 0; i < halPort->num_formats; ++i) {
+        halPort->formats[i] = static_cast<audio_format_t>(port.formats[i]);
+    }
+    halPort->num_gains = std::min(port.gains.size(), static_cast<size_t>(AUDIO_PORT_MAX_GAINS));
+    for (size_t i = 0; i < halPort->num_gains; ++i) {
+        audioGainToHal(port.gains[i], &halPort->gains[i]);
+    }
+    audioPortConfigToHal(port.activeConfig, &halPort->active_config);
+    switch (port.type) {
+        case AudioPortType::NONE: break;
+        case AudioPortType::DEVICE: {
+            halPort->ext.device.hw_module = port.ext.device.hwModule;
+            halPort->ext.device.type = static_cast<audio_devices_t>(port.ext.device.type);
+            memcpy(halPort->ext.device.address,
+                    port.ext.device.address.data(),
+                    AUDIO_DEVICE_MAX_ADDRESS_LEN);
+            break;
+        }
+        case AudioPortType::MIX: {
+            halPort->ext.mix.hw_module = port.ext.mix.hwModule;
+            halPort->ext.mix.handle = port.ext.mix.ioHandle;
+            halPort->ext.mix.latency_class =
+                    static_cast<audio_mix_latency_class_t>(port.ext.mix.latencyClass);
+            break;
+        }
+        case AudioPortType::SESSION: {
+            halPort->ext.session.session = static_cast<audio_session_t>(port.ext.session.session);
+            break;
+        }
+    }
+}
+
+void HidlUtils::uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid) {
+    uuid->timeLow = halUuid.timeLow;
+    uuid->timeMid = halUuid.timeMid;
+    uuid->versionAndTimeHigh = halUuid.timeHiAndVersion;
+    uuid->variantAndClockSeqHigh = halUuid.clockSeq;
+    memcpy(uuid->node.data(), halUuid.node, uuid->node.size());
+}
+
+void HidlUtils::uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid) {
+    halUuid->timeLow = uuid.timeLow;
+    halUuid->timeMid = uuid.timeMid;
+    halUuid->timeHiAndVersion = uuid.versionAndTimeHigh;
+    halUuid->clockSeq = uuid.variantAndClockSeqHigh;
+    memcpy(halUuid->node, uuid.node.data(), uuid.node.size());
+}
+
+}  // namespace android
diff --git a/audio/common/2.0/default/HidlUtils.h b/audio/common/2.0/default/HidlUtils.h
new file mode 100644
index 0000000..3fde4d7
--- /dev/null
+++ b/audio/common/2.0/default/HidlUtils.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_V2_0_Hidl_Utils_H_
+#define android_hardware_audio_V2_0_Hidl_Utils_H_
+
+#include <memory>
+
+#include <android/hardware/audio/common/2.0/types.h>
+#include <system/audio.h>
+
+using ::android::hardware::audio::common::V2_0::AudioConfig;
+using ::android::hardware::audio::common::V2_0::AudioGain;
+using ::android::hardware::audio::common::V2_0::AudioGainConfig;
+using ::android::hardware::audio::common::V2_0::AudioOffloadInfo;
+using ::android::hardware::audio::common::V2_0::AudioPort;
+using ::android::hardware::audio::common::V2_0::AudioPortConfig;
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::hidl_vec;
+
+namespace android {
+
+class HidlUtils {
+  public:
+    static void audioConfigFromHal(const audio_config_t& halConfig, AudioConfig* config);
+    static void audioConfigToHal(const AudioConfig& config, audio_config_t* halConfig);
+    static void audioGainConfigFromHal(
+            const struct audio_gain_config& halConfig, AudioGainConfig* config);
+    static void audioGainConfigToHal(
+            const AudioGainConfig& config, struct audio_gain_config* halConfig);
+    static void audioGainFromHal(const struct audio_gain& halGain, AudioGain* gain);
+    static void audioGainToHal(const AudioGain& gain, struct audio_gain* halGain);
+    static void audioOffloadInfoFromHal(
+            const audio_offload_info_t& halOffload, AudioOffloadInfo* offload);
+    static void audioOffloadInfoToHal(
+            const AudioOffloadInfo& offload, audio_offload_info_t* halOffload);
+    static void audioPortConfigFromHal(
+            const struct audio_port_config& halConfig, AudioPortConfig* config);
+    static void audioPortConfigToHal(
+            const AudioPortConfig& config, struct audio_port_config* halConfig);
+    static void audioPortConfigsFromHal(
+            unsigned int numHalConfigs, const struct audio_port_config *halConfigs,
+            hidl_vec<AudioPortConfig> *configs);
+    static std::unique_ptr<audio_port_config[]> audioPortConfigsToHal(
+            const hidl_vec<AudioPortConfig>& configs);
+    static void audioPortFromHal(const struct audio_port& halPort, AudioPort* port);
+    static void audioPortToHal(const AudioPort& port, struct audio_port* halPort);
+    static void uuidFromHal(const audio_uuid_t& halUuid, Uuid* uuid);
+    static void uuidToHal(const Uuid& uuid, audio_uuid_t* halUuid);
+};
+
+}  // namespace android
+
+#endif  // android_hardware_audio_V2_0_Hidl_Utils_H_
diff --git a/audio/common/2.0/types.hal b/audio/common/2.0/types.hal
new file mode 100644
index 0000000..eec4ac2
--- /dev/null
+++ b/audio/common/2.0/types.hal
@@ -0,0 +1,931 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.common@2.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 intented 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
+    // TODO: Synchronization should be done automatically by tools
+    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
+    PUBLIC_CNT       = ACCESSIBILITY + 1,
+    // Number of streams considered by audio policy for volume and routing
+    FOR_POLICY_CNT   = PATCH,
+    CNT              = PATCH + 1
+};
+
+@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,
+
+    CNT,
+    MAX                 = CNT - 1,
+    FM_TUNER            = 1998,
+    /*
+     * A low-priority, preemptible audio source for for background software
+     * hotword detection. Same tuning as VOICE_RECOGNITION.  Used only
+     * internally by the framework.
+     */
+    HOTWORD             = 1999
+};
+
+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 TODO use unique values for
+     * AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE, after all uses have
+     * been updated from 0 to the appropriate symbol, and have been tested.
+     * 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, /* DO NOT CHANGE */
+    MP3                 = 0x01000000UL,
+    AMR_NB              = 0x02000000UL,
+    AMR_WB              = 0x03000000UL,
+    AAC                 = 0x04000000UL,
+    HE_AAC_V1           = 0x05000000UL, /* Deprecated, Use AAC_HE_V1*/
+    HE_AAC_V2           = 0x06000000UL, /* Deprecated, Use AAC_HE_V2*/
+    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,
+    LDAC                = 0x22000000UL,
+    MAIN_MASK           = 0xFF000000UL, /* Deprecated */
+    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,
+
+    VORBIS_SUB_NONE       = 0x0,
+
+    /* 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_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)
+};
+
+/*
+ * 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 {
+    REPRESENTATION_POSITION = 0, /* must be 0 for compatibility */
+    /* 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_MONO     = OUT_FRONT_LEFT,
+    OUT_STEREO   = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT),
+    OUT_2POINT1  = (OUT_FRONT_LEFT | OUT_FRONT_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),
+    OUT_ALL      = (OUT_FRONT_LEFT | OUT_FRONT_RIGHT |
+            OUT_FRONT_CENTER | OUT_LOW_FREQUENCY |
+            OUT_BACK_LEFT | OUT_BACK_RIGHT |
+            OUT_FRONT_LEFT_OF_CENTER | OUT_FRONT_RIGHT_OF_CENTER |
+            OUT_BACK_CENTER |
+            OUT_SIDE_LEFT | OUT_SIDE_RIGHT |
+            OUT_TOP_CENTER |
+            OUT_TOP_FRONT_LEFT | OUT_TOP_FRONT_CENTER | OUT_TOP_FRONT_RIGHT |
+            OUT_TOP_BACK_LEFT | OUT_TOP_BACK_CENTER | OUT_TOP_BACK_RIGHT),
+
+    /* 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_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_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),
+    IN_ALL    = (IN_LEFT | IN_RIGHT | IN_FRONT | IN_BACK|
+            IN_LEFT_PROCESSED | IN_RIGHT_PROCESSED |
+            IN_FRONT_PROCESSED | IN_BACK_PROCESSED|
+            IN_PRESSURE |
+            IN_X_AXIS | IN_Y_AXIS | IN_Z_AXIS |
+            IN_VOICE_UPLINK | IN_VOICE_DNLINK),
+
+    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)
+};
+
+
+/*
+ * Expresses the convention when stereo audio samples are stored interleaved
+ * in an array.  This should improve readability by allowing code to use
+ * symbolic indices instead of hard-coded [0] and [1].
+ *
+ * For multi-channel beyond stereo, the platform convention is that channels
+ * are interleaved in order from least significant channel mask bit to most
+ * significant channel mask bit, with unused bits skipped.  Any exceptions
+ * to this convention will be noted at the appropriate API.
+ */
+@export(name="", value_prefix="AUDIO_INTERLEAVE_")
+enum AudioInterleave : int32_t {
+    LEFT   = 0,
+    RIGHT  = 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 {
+    INVALID          = -2,
+    CURRENT          = -1,
+    NORMAL           = 0,
+    RINGTONE         = 1,
+    IN_CALL          = 2,
+    IN_COMMUNICATION = 3,
+
+    CNT,
+    MAX              = CNT - 1,
+};
+
+@export(name="", value_prefix="AUDIO_DEVICE_")
+enum AudioDevice : uint32_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_DEFAULT                   = BIT_DEFAULT,
+    OUT_ALL      = (OUT_EARPIECE |
+            OUT_SPEAKER |
+            OUT_WIRED_HEADSET |
+            OUT_WIRED_HEADPHONE |
+            OUT_BLUETOOTH_SCO |
+            OUT_BLUETOOTH_SCO_HEADSET |
+            OUT_BLUETOOTH_SCO_CARKIT |
+            OUT_BLUETOOTH_A2DP |
+            OUT_BLUETOOTH_A2DP_HEADPHONES |
+            OUT_BLUETOOTH_A2DP_SPEAKER |
+            OUT_HDMI |
+            OUT_ANLG_DOCK_HEADSET |
+            OUT_DGTL_DOCK_HEADSET |
+            OUT_USB_ACCESSORY |
+            OUT_USB_DEVICE |
+            OUT_REMOTE_SUBMIX |
+            OUT_TELEPHONY_TX |
+            OUT_LINE |
+            OUT_HDMI_ARC |
+            OUT_SPDIF |
+            OUT_FM |
+            OUT_AUX_LINE |
+            OUT_SPEAKER_SAFE |
+            OUT_IP |
+            OUT_BUS |
+            OUT_PROXY |
+            OUT_DEFAULT),
+    OUT_ALL_A2DP = (OUT_BLUETOOTH_A2DP |
+            OUT_BLUETOOTH_A2DP_HEADPHONES |
+            OUT_BLUETOOTH_A2DP_SPEAKER),
+    OUT_ALL_SCO  = (OUT_BLUETOOTH_SCO |
+            OUT_BLUETOOTH_SCO_HEADSET |
+            OUT_BLUETOOTH_SCO_CARKIT),
+    OUT_ALL_USB  = (OUT_USB_ACCESSORY | OUT_USB_DEVICE),
+    /* 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_DEFAULT               = BIT_IN | BIT_DEFAULT,
+
+    IN_ALL     = (IN_COMMUNICATION |
+            IN_AMBIENT |
+            IN_BUILTIN_MIC |
+            IN_BLUETOOTH_SCO_HEADSET |
+            IN_WIRED_HEADSET |
+            IN_HDMI |
+            IN_TELEPHONY_RX |
+            IN_BACK_MIC |
+            IN_REMOTE_SUBMIX |
+            IN_ANLG_DOCK_HEADSET |
+            IN_DGTL_DOCK_HEADSET |
+            IN_USB_ACCESSORY |
+            IN_USB_DEVICE |
+            IN_FM_TUNER |
+            IN_TV_TUNER |
+            IN_LINE |
+            IN_SPDIF |
+            IN_BLUETOOTH_A2DP |
+            IN_LOOPBACK |
+            IN_IP |
+            IN_BUS |
+            IN_PROXY |
+            IN_DEFAULT),
+    IN_ALL_SCO = IN_BLUETOOTH_SCO_HEADSET,
+    IN_ALL_USB  = (IN_USB_ACCESSORY | IN_USB_DEVICE),
+};
+
+/*
+ * 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.
+};
+
+/*
+ * 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.
+};
+
+@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
+    // TODO: Synchronization should be done automatically by tools
+    UNKNOWN                            = 0,
+    MEDIA                              = 1,
+    VOICE_COMMUNICATION                = 2,
+    VOICE_COMMUNICATION_SIGNALLING     = 3,
+    ALARM                              = 4,
+    NOTIFICATION                       = 5,
+    NOTIFICATION_TELEPHONY_RINGTONE    = 6,
+    NOTIFICATION_COMMUNICATION_REQUEST = 7,
+    NOTIFICATION_COMMUNICATION_INSTANT = 8,
+    NOTIFICATION_COMMUNICATION_DELAYED = 9,
+    NOTIFICATION_EVENT                 = 10,
+    ASSISTANCE_ACCESSIBILITY           = 11,
+    ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
+    ASSISTANCE_SONIFICATION            = 13,
+    GAME                               = 14,
+    VIRTUAL_SOURCE                     = 15,
+    ASSISTANT                          = 16,
+
+    CNT,
+    MAX                                = CNT - 1,
+};
+
+/*
+ * Additional information about the stream passed to hardware decoders.
+ */
+struct AudioOffloadInfo {
+    uint32_t sampleRateHz;
+    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;
+    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 {
+    AudioGainMode mode;
+    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,
+    ALL = SAMPLE_RATE | CHANNEL_MASK | FORMAT | GAIN
+};
+
+/*
+ * Audio port configuration structure used to specify a particular configuration
+ * of an audio port.
+ */
+struct AudioPortConfig {
+    AudioPortHandle id;
+    AudioPortConfigMask configMask;
+    uint32_t sampleRateHz;
+    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;
+    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<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;
+};
diff --git a/audio/common/2.0/vts/types.vts b/audio/common/2.0/vts/types.vts
new file mode 100644
index 0000000..8d1a9db
--- /dev/null
+++ b/audio/common/2.0/vts/types.vts
@@ -0,0 +1,1927 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "types"
+
+package: "android.hardware.audio.common"
+
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioHandleConsts"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "AUDIO_IO_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_MODULE_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_PORT_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_PATCH_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::Uuid"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "timeLow"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "timeMid"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "versionAndTimeHigh"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "variantAndClockSeqHigh"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "node"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 6
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioStreamType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "MIN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "VOICE_CALL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SYSTEM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "RING"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "MUSIC"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ALARM"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NOTIFICATION"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "BLUETOOTH_SCO"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "ENFORCED_AUDIBLE"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "DTMF"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "TTS"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "ACCESSIBILITY"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "REROUTING"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "PATCH"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "PUBLIC_CNT"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "FOR_POLICY_CNT"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 13
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioSource"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MIC"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "VOICE_UPLINK"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VOICE_DOWNLINK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "VOICE_CALL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CAMCORDER"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "VOICE_RECOGNITION"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "VOICE_COMMUNICATION"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "REMOTE_SUBMIX"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "UNPROCESSED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "FM_TUNER"
+        scalar_value: {
+            int32_t: 1998
+        }
+        enumerator: "HOTWORD"
+        scalar_value: {
+            int32_t: 1999
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioSessionConsts"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OUTPUT_STAGE"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "OUTPUT_MIX"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ALLOCATE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioFormat"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            uint32_t: 4294967295
+        }
+        enumerator: "DEFAULT"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "PCM"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "MP3"
+        scalar_value: {
+            uint32_t: 16777216
+        }
+        enumerator: "AMR_NB"
+        scalar_value: {
+            uint32_t: 33554432
+        }
+        enumerator: "AMR_WB"
+        scalar_value: {
+            uint32_t: 50331648
+        }
+        enumerator: "AAC"
+        scalar_value: {
+            uint32_t: 67108864
+        }
+        enumerator: "HE_AAC_V1"
+        scalar_value: {
+            uint32_t: 83886080
+        }
+        enumerator: "HE_AAC_V2"
+        scalar_value: {
+            uint32_t: 100663296
+        }
+        enumerator: "VORBIS"
+        scalar_value: {
+            uint32_t: 117440512
+        }
+        enumerator: "OPUS"
+        scalar_value: {
+            uint32_t: 134217728
+        }
+        enumerator: "AC3"
+        scalar_value: {
+            uint32_t: 150994944
+        }
+        enumerator: "E_AC3"
+        scalar_value: {
+            uint32_t: 167772160
+        }
+        enumerator: "DTS"
+        scalar_value: {
+            uint32_t: 184549376
+        }
+        enumerator: "DTS_HD"
+        scalar_value: {
+            uint32_t: 201326592
+        }
+        enumerator: "IEC61937"
+        scalar_value: {
+            uint32_t: 218103808
+        }
+        enumerator: "DOLBY_TRUEHD"
+        scalar_value: {
+            uint32_t: 234881024
+        }
+        enumerator: "EVRC"
+        scalar_value: {
+            uint32_t: 268435456
+        }
+        enumerator: "EVRCB"
+        scalar_value: {
+            uint32_t: 285212672
+        }
+        enumerator: "EVRCWB"
+        scalar_value: {
+            uint32_t: 301989888
+        }
+        enumerator: "EVRCNW"
+        scalar_value: {
+            uint32_t: 318767104
+        }
+        enumerator: "AAC_ADIF"
+        scalar_value: {
+            uint32_t: 335544320
+        }
+        enumerator: "WMA"
+        scalar_value: {
+            uint32_t: 352321536
+        }
+        enumerator: "WMA_PRO"
+        scalar_value: {
+            uint32_t: 369098752
+        }
+        enumerator: "AMR_WB_PLUS"
+        scalar_value: {
+            uint32_t: 385875968
+        }
+        enumerator: "MP2"
+        scalar_value: {
+            uint32_t: 402653184
+        }
+        enumerator: "QCELP"
+        scalar_value: {
+            uint32_t: 419430400
+        }
+        enumerator: "DSD"
+        scalar_value: {
+            uint32_t: 436207616
+        }
+        enumerator: "FLAC"
+        scalar_value: {
+            uint32_t: 452984832
+        }
+        enumerator: "ALAC"
+        scalar_value: {
+            uint32_t: 469762048
+        }
+        enumerator: "APE"
+        scalar_value: {
+            uint32_t: 486539264
+        }
+        enumerator: "AAC_ADTS"
+        scalar_value: {
+            uint32_t: 503316480
+        }
+        enumerator: "SBC"
+        scalar_value: {
+            uint32_t: 520093696
+        }
+        enumerator: "APTX"
+        scalar_value: {
+            uint32_t: 536870912
+        }
+        enumerator: "APTX_HD"
+        scalar_value: {
+            uint32_t: 553648128
+        }
+        enumerator: "LDAC"
+        scalar_value: {
+            uint32_t: 570425344
+        }
+        enumerator: "MAIN_MASK"
+        scalar_value: {
+            uint32_t: 4278190080
+        }
+        enumerator: "SUB_MASK"
+        scalar_value: {
+            uint32_t: 16777215
+        }
+        enumerator: "PCM_SUB_16_BIT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "PCM_SUB_8_BIT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "PCM_SUB_32_BIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "PCM_SUB_8_24_BIT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PCM_SUB_FLOAT"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "PCM_SUB_24_BIT_PACKED"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "MP3_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "AMR_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "AAC_SUB_MAIN"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "AAC_SUB_LC"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "AAC_SUB_SSR"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "AAC_SUB_LTP"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "AAC_SUB_HE_V1"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "AAC_SUB_SCALABLE"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "AAC_SUB_ERLC"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "AAC_SUB_LD"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "AAC_SUB_HE_V2"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "AAC_SUB_ELD"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "VORBIS_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "PCM_16_BIT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "PCM_8_BIT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "PCM_32_BIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "PCM_8_24_BIT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PCM_FLOAT"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "PCM_24_BIT_PACKED"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "AAC_MAIN"
+        scalar_value: {
+            uint32_t: 67108865
+        }
+        enumerator: "AAC_LC"
+        scalar_value: {
+            uint32_t: 67108866
+        }
+        enumerator: "AAC_SSR"
+        scalar_value: {
+            uint32_t: 67108868
+        }
+        enumerator: "AAC_LTP"
+        scalar_value: {
+            uint32_t: 67108872
+        }
+        enumerator: "AAC_HE_V1"
+        scalar_value: {
+            uint32_t: 67108880
+        }
+        enumerator: "AAC_SCALABLE"
+        scalar_value: {
+            uint32_t: 67108896
+        }
+        enumerator: "AAC_ERLC"
+        scalar_value: {
+            uint32_t: 67108928
+        }
+        enumerator: "AAC_LD"
+        scalar_value: {
+            uint32_t: 67108992
+        }
+        enumerator: "AAC_HE_V2"
+        scalar_value: {
+            uint32_t: 67109120
+        }
+        enumerator: "AAC_ELD"
+        scalar_value: {
+            uint32_t: 67109376
+        }
+        enumerator: "AAC_ADTS_MAIN"
+        scalar_value: {
+            uint32_t: 503316481
+        }
+        enumerator: "AAC_ADTS_LC"
+        scalar_value: {
+            uint32_t: 503316482
+        }
+        enumerator: "AAC_ADTS_SSR"
+        scalar_value: {
+            uint32_t: 503316484
+        }
+        enumerator: "AAC_ADTS_LTP"
+        scalar_value: {
+            uint32_t: 503316488
+        }
+        enumerator: "AAC_ADTS_HE_V1"
+        scalar_value: {
+            uint32_t: 503316496
+        }
+        enumerator: "AAC_ADTS_SCALABLE"
+        scalar_value: {
+            uint32_t: 503316512
+        }
+        enumerator: "AAC_ADTS_ERLC"
+        scalar_value: {
+            uint32_t: 503316544
+        }
+        enumerator: "AAC_ADTS_LD"
+        scalar_value: {
+            uint32_t: 503316608
+        }
+        enumerator: "AAC_ADTS_HE_V2"
+        scalar_value: {
+            uint32_t: 503316736
+        }
+        enumerator: "AAC_ADTS_ELD"
+        scalar_value: {
+            uint32_t: 503316992
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::FixedChannelCount"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FCC_2"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FCC_8"
+        scalar_value: {
+            int32_t: 8
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "REPRESENTATION_POSITION"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "REPRESENTATION_INDEX"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "INVALID"
+        scalar_value: {
+            uint32_t: 3221225472
+        }
+        enumerator: "OUT_FRONT_LEFT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_FRONT_RIGHT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "OUT_FRONT_CENTER"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "OUT_LOW_FREQUENCY"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "OUT_BACK_LEFT"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "OUT_BACK_RIGHT"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "OUT_FRONT_LEFT_OF_CENTER"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "OUT_FRONT_RIGHT_OF_CENTER"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "OUT_BACK_CENTER"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "OUT_SIDE_LEFT"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "OUT_SIDE_RIGHT"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_TOP_CENTER"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "OUT_TOP_FRONT_LEFT"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "OUT_TOP_FRONT_CENTER"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "OUT_TOP_FRONT_RIGHT"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "OUT_TOP_BACK_LEFT"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "OUT_TOP_BACK_CENTER"
+        scalar_value: {
+            uint32_t: 65536
+        }
+        enumerator: "OUT_TOP_BACK_RIGHT"
+        scalar_value: {
+            uint32_t: 131072
+        }
+        enumerator: "OUT_MONO"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_STEREO"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "OUT_2POINT1"
+        scalar_value: {
+            uint32_t: 11
+        }
+        enumerator: "OUT_QUAD"
+        scalar_value: {
+            uint32_t: 51
+        }
+        enumerator: "OUT_QUAD_BACK"
+        scalar_value: {
+            uint32_t: 51
+        }
+        enumerator: "OUT_QUAD_SIDE"
+        scalar_value: {
+            uint32_t: 1539
+        }
+        enumerator: "OUT_SURROUND"
+        scalar_value: {
+            uint32_t: 263
+        }
+        enumerator: "OUT_PENTA"
+        scalar_value: {
+            uint32_t: 55
+        }
+        enumerator: "OUT_5POINT1"
+        scalar_value: {
+            uint32_t: 63
+        }
+        enumerator: "OUT_5POINT1_BACK"
+        scalar_value: {
+            uint32_t: 63
+        }
+        enumerator: "OUT_5POINT1_SIDE"
+        scalar_value: {
+            uint32_t: 1551
+        }
+        enumerator: "OUT_6POINT1"
+        scalar_value: {
+            uint32_t: 319
+        }
+        enumerator: "OUT_7POINT1"
+        scalar_value: {
+            uint32_t: 1599
+        }
+        enumerator: "OUT_ALL"
+        scalar_value: {
+            uint32_t: 262143
+        }
+        enumerator: "IN_LEFT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "IN_RIGHT"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "IN_FRONT"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "IN_BACK"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "IN_LEFT_PROCESSED"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "IN_RIGHT_PROCESSED"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "IN_FRONT_PROCESSED"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "IN_BACK_PROCESSED"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "IN_PRESSURE"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "IN_X_AXIS"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "IN_Y_AXIS"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "IN_Z_AXIS"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "IN_VOICE_UPLINK"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "IN_VOICE_DNLINK"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "IN_MONO"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "IN_STEREO"
+        scalar_value: {
+            uint32_t: 12
+        }
+        enumerator: "IN_FRONT_BACK"
+        scalar_value: {
+            uint32_t: 48
+        }
+        enumerator: "IN_VOICE_UPLINK_MONO"
+        scalar_value: {
+            uint32_t: 16400
+        }
+        enumerator: "IN_VOICE_DNLINK_MONO"
+        scalar_value: {
+            uint32_t: 32784
+        }
+        enumerator: "IN_VOICE_CALL_MONO"
+        scalar_value: {
+            uint32_t: 49168
+        }
+        enumerator: "IN_ALL"
+        scalar_value: {
+            uint32_t: 65532
+        }
+        enumerator: "COUNT_MAX"
+        scalar_value: {
+            uint32_t: 30
+        }
+        enumerator: "INDEX_HDR"
+        scalar_value: {
+            uint32_t: 2147483648
+        }
+        enumerator: "INDEX_MASK_1"
+        scalar_value: {
+            uint32_t: 2147483649
+        }
+        enumerator: "INDEX_MASK_2"
+        scalar_value: {
+            uint32_t: 2147483651
+        }
+        enumerator: "INDEX_MASK_3"
+        scalar_value: {
+            uint32_t: 2147483655
+        }
+        enumerator: "INDEX_MASK_4"
+        scalar_value: {
+            uint32_t: 2147483663
+        }
+        enumerator: "INDEX_MASK_5"
+        scalar_value: {
+            uint32_t: 2147483679
+        }
+        enumerator: "INDEX_MASK_6"
+        scalar_value: {
+            uint32_t: 2147483711
+        }
+        enumerator: "INDEX_MASK_7"
+        scalar_value: {
+            uint32_t: 2147483775
+        }
+        enumerator: "INDEX_MASK_8"
+        scalar_value: {
+            uint32_t: 2147483903
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioInterleave"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "LEFT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RIGHT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            int32_t: -2
+        }
+        enumerator: "CURRENT"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RINGTONE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "IN_CALL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "IN_COMMUNICATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioDevice"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "BIT_IN"
+        scalar_value: {
+            uint32_t: 2147483648
+        }
+        enumerator: "BIT_DEFAULT"
+        scalar_value: {
+            uint32_t: 1073741824
+        }
+        enumerator: "OUT_EARPIECE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_SPEAKER"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "OUT_WIRED_HEADSET"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "OUT_WIRED_HEADPHONE"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "OUT_BLUETOOTH_SCO"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "OUT_BLUETOOTH_SCO_HEADSET"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "OUT_BLUETOOTH_SCO_CARKIT"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP_HEADPHONES"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP_SPEAKER"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "OUT_AUX_DIGITAL"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_HDMI"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_ANLG_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "OUT_DGTL_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "OUT_USB_ACCESSORY"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "OUT_USB_DEVICE"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "OUT_REMOTE_SUBMIX"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "OUT_TELEPHONY_TX"
+        scalar_value: {
+            uint32_t: 65536
+        }
+        enumerator: "OUT_LINE"
+        scalar_value: {
+            uint32_t: 131072
+        }
+        enumerator: "OUT_HDMI_ARC"
+        scalar_value: {
+            uint32_t: 262144
+        }
+        enumerator: "OUT_SPDIF"
+        scalar_value: {
+            uint32_t: 524288
+        }
+        enumerator: "OUT_FM"
+        scalar_value: {
+            uint32_t: 1048576
+        }
+        enumerator: "OUT_AUX_LINE"
+        scalar_value: {
+            uint32_t: 2097152
+        }
+        enumerator: "OUT_SPEAKER_SAFE"
+        scalar_value: {
+            uint32_t: 4194304
+        }
+        enumerator: "OUT_IP"
+        scalar_value: {
+            uint32_t: 8388608
+        }
+        enumerator: "OUT_BUS"
+        scalar_value: {
+            uint32_t: 16777216
+        }
+        enumerator: "OUT_PROXY"
+        scalar_value: {
+            uint32_t: 33554432
+        }
+        enumerator: "OUT_DEFAULT"
+        scalar_value: {
+            uint32_t: 1073741824
+        }
+        enumerator: "OUT_ALL"
+        scalar_value: {
+            uint32_t: 1140850687
+        }
+        enumerator: "OUT_ALL_A2DP"
+        scalar_value: {
+            uint32_t: 896
+        }
+        enumerator: "OUT_ALL_SCO"
+        scalar_value: {
+            uint32_t: 112
+        }
+        enumerator: "OUT_ALL_USB"
+        scalar_value: {
+            uint32_t: 24576
+        }
+        enumerator: "IN_COMMUNICATION"
+        scalar_value: {
+            uint32_t: 2147483649
+        }
+        enumerator: "IN_AMBIENT"
+        scalar_value: {
+            uint32_t: 2147483650
+        }
+        enumerator: "IN_BUILTIN_MIC"
+        scalar_value: {
+            uint32_t: 2147483652
+        }
+        enumerator: "IN_BLUETOOTH_SCO_HEADSET"
+        scalar_value: {
+            uint32_t: 2147483656
+        }
+        enumerator: "IN_WIRED_HEADSET"
+        scalar_value: {
+            uint32_t: 2147483664
+        }
+        enumerator: "IN_AUX_DIGITAL"
+        scalar_value: {
+            uint32_t: 2147483680
+        }
+        enumerator: "IN_HDMI"
+        scalar_value: {
+            uint32_t: 2147483680
+        }
+        enumerator: "IN_VOICE_CALL"
+        scalar_value: {
+            uint32_t: 2147483712
+        }
+        enumerator: "IN_TELEPHONY_RX"
+        scalar_value: {
+            uint32_t: 2147483712
+        }
+        enumerator: "IN_BACK_MIC"
+        scalar_value: {
+            uint32_t: 2147483776
+        }
+        enumerator: "IN_REMOTE_SUBMIX"
+        scalar_value: {
+            uint32_t: 2147483904
+        }
+        enumerator: "IN_ANLG_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2147484160
+        }
+        enumerator: "IN_DGTL_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2147484672
+        }
+        enumerator: "IN_USB_ACCESSORY"
+        scalar_value: {
+            uint32_t: 2147485696
+        }
+        enumerator: "IN_USB_DEVICE"
+        scalar_value: {
+            uint32_t: 2147487744
+        }
+        enumerator: "IN_FM_TUNER"
+        scalar_value: {
+            uint32_t: 2147491840
+        }
+        enumerator: "IN_TV_TUNER"
+        scalar_value: {
+            uint32_t: 2147500032
+        }
+        enumerator: "IN_LINE"
+        scalar_value: {
+            uint32_t: 2147516416
+        }
+        enumerator: "IN_SPDIF"
+        scalar_value: {
+            uint32_t: 2147549184
+        }
+        enumerator: "IN_BLUETOOTH_A2DP"
+        scalar_value: {
+            uint32_t: 2147614720
+        }
+        enumerator: "IN_LOOPBACK"
+        scalar_value: {
+            uint32_t: 2147745792
+        }
+        enumerator: "IN_IP"
+        scalar_value: {
+            uint32_t: 2148007936
+        }
+        enumerator: "IN_BUS"
+        scalar_value: {
+            uint32_t: 2148532224
+        }
+        enumerator: "IN_PROXY"
+        scalar_value: {
+            uint32_t: 2164260864
+        }
+        enumerator: "IN_DEFAULT"
+        scalar_value: {
+            uint32_t: 3221225472
+        }
+        enumerator: "IN_ALL"
+        scalar_value: {
+            uint32_t: 3240099839
+        }
+        enumerator: "IN_ALL_SCO"
+        scalar_value: {
+            uint32_t: 2147483656
+        }
+        enumerator: "IN_ALL_USB"
+        scalar_value: {
+            uint32_t: 2147489792
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioOutputFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DIRECT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "PRIMARY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FAST"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "DEEP_BUFFER"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "COMPRESS_OFFLOAD"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "NON_BLOCKING"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "HW_AV_SYNC"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "TTS"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "RAW"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "SYNC"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "IEC958_NONAUDIO"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "DIRECT_PCM"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "MMAP_NOIRQ"
+        scalar_value: {
+            int32_t: 16384
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioInputFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FAST"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "HW_HOTWORD"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "RAW"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SYNC"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "MMAP_NOIRQ"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioUsage"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MEDIA"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "VOICE_COMMUNICATION"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VOICE_COMMUNICATION_SIGNALLING"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ALARM"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NOTIFICATION"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "NOTIFICATION_TELEPHONY_RINGTONE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_REQUEST"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_INSTANT"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_DELAYED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "NOTIFICATION_EVENT"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "ASSISTANCE_ACCESSIBILITY"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "ASSISTANCE_NAVIGATION_GUIDANCE"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "ASSISTANCE_SONIFICATION"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "GAME"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "VIRTUAL_SOURCE"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioOffloadInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "streamType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioStreamType"
+    }
+    struct_value: {
+        name: "bitRatePerSecond"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "durationMicroseconds"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "hasVideo"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "isStreaming"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "bitWidth"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "bufferSize"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "usage"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioUsage"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "offloadInfo"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioOffloadInfo"
+    }
+    struct_value: {
+        name: "frameCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "JOINT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "CHANNELS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "RAMP"
+        scalar_value: {
+            uint32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGain"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "minValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "defaultValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "stepValue"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "minRampMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "maxRampMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGainConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "index"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "mode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "values"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+    struct_value: {
+        name: "rampDurationMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SOURCE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SINK"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DEVICE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MIX"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SESSION"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigDeviceExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioDevice"
+    }
+    struct_value: {
+        name: "address"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigSessionExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "session"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigMask"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SAMPLE_RATE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "CHANNEL_MASK"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "FORMAT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "GAIN"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "ALL"
+        scalar_value: {
+            uint32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfig"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext"
+        type: TYPE_UNION
+        sub_union: {
+            name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt"
+            type: TYPE_STRUCT
+            sub_struct: {
+                name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt::UseCase"
+                type: TYPE_UNION
+                union_value: {
+                    name: "stream"
+                    type: TYPE_ENUM
+                    predefined_type: "::android::hardware::audio::common::V2_0::AudioStreamType"
+                }
+                union_value: {
+                    name: "source"
+                    type: TYPE_ENUM
+                    predefined_type: "::android::hardware::audio::common::V2_0::AudioSource"
+                }
+            }
+            struct_value: {
+                name: "hwModule"
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+            struct_value: {
+                name: "ioHandle"
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+            struct_value: {
+                name: "useCase"
+                type: TYPE_UNION
+                predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt::UseCase"
+            }
+        }
+        union_value: {
+            name: "device"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigDeviceExt"
+        }
+        union_value: {
+            name: "mix"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt"
+        }
+        union_value: {
+            name: "session"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigSessionExt"
+        }
+    }
+    struct_value: {
+        name: "id"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "configMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigMask"
+    }
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "gain"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainConfig"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortType"
+    }
+    struct_value: {
+        name: "role"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    }
+    struct_value: {
+        name: "ext"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortDeviceExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioDevice"
+    }
+    struct_value: {
+        name: "address"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioMixLatencyClass"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "LOW"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortMixExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "ioHandle"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "latencyClass"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioMixLatencyClass"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortSessionExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "session"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPort"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::audio::common::V2_0::AudioPort::Ext"
+        type: TYPE_UNION
+        union_value: {
+            name: "device"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortDeviceExt"
+        }
+        union_value: {
+            name: "mix"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortMixExt"
+        }
+        union_value: {
+            name: "session"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortSessionExt"
+        }
+    }
+    struct_value: {
+        name: "id"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "role"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "sampleRates"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+    struct_value: {
+        name: "channelMasks"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+        }
+    }
+    struct_value: {
+        name: "formats"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+        }
+    }
+    struct_value: {
+        name: "gains"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioGain"
+        }
+    }
+    struct_value: {
+        name: "activeConfig"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortType"
+    }
+    struct_value: {
+        name: "ext"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPort::Ext"
+    }
+}
+
diff --git a/audio/common/Android.mk b/audio/common/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/common/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
new file mode 100644
index 0000000..ee76a0e
--- /dev/null
+++ b/audio/effect/2.0/Android.bp
@@ -0,0 +1,162 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.audio.effect@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio.effect@2.0",
+    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",
+    ],
+    out: [
+        "android/hardware/audio/effect/2.0/types.cpp",
+        "android/hardware/audio/effect/2.0/AcousticEchoCancelerEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/AutomaticGainControlEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/BassBoostEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/DownmixEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/EffectAll.cpp",
+        "android/hardware/audio/effect/2.0/EffectBufferProviderCallbackAll.cpp",
+        "android/hardware/audio/effect/2.0/EffectsFactoryAll.cpp",
+        "android/hardware/audio/effect/2.0/EnvironmentalReverbEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/EqualizerEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/LoudnessEnhancerEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/NoiseSuppressionEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/PresetReverbEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/VirtualizerEffectAll.cpp",
+        "android/hardware/audio/effect/2.0/VisualizerEffectAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.audio.effect@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.audio.effect@2.0",
+    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",
+    ],
+    out: [
+        "android/hardware/audio/effect/2.0/types.h",
+        "android/hardware/audio/effect/2.0/IAcousticEchoCancelerEffect.h",
+        "android/hardware/audio/effect/2.0/IHwAcousticEchoCancelerEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwAcousticEchoCancelerEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwAcousticEchoCancelerEffect.h",
+        "android/hardware/audio/effect/2.0/BsAcousticEchoCancelerEffect.h",
+        "android/hardware/audio/effect/2.0/IAutomaticGainControlEffect.h",
+        "android/hardware/audio/effect/2.0/IHwAutomaticGainControlEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwAutomaticGainControlEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwAutomaticGainControlEffect.h",
+        "android/hardware/audio/effect/2.0/BsAutomaticGainControlEffect.h",
+        "android/hardware/audio/effect/2.0/IBassBoostEffect.h",
+        "android/hardware/audio/effect/2.0/IHwBassBoostEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwBassBoostEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwBassBoostEffect.h",
+        "android/hardware/audio/effect/2.0/BsBassBoostEffect.h",
+        "android/hardware/audio/effect/2.0/IDownmixEffect.h",
+        "android/hardware/audio/effect/2.0/IHwDownmixEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwDownmixEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwDownmixEffect.h",
+        "android/hardware/audio/effect/2.0/BsDownmixEffect.h",
+        "android/hardware/audio/effect/2.0/IEffect.h",
+        "android/hardware/audio/effect/2.0/IHwEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwEffect.h",
+        "android/hardware/audio/effect/2.0/BsEffect.h",
+        "android/hardware/audio/effect/2.0/IEffectBufferProviderCallback.h",
+        "android/hardware/audio/effect/2.0/IHwEffectBufferProviderCallback.h",
+        "android/hardware/audio/effect/2.0/BnHwEffectBufferProviderCallback.h",
+        "android/hardware/audio/effect/2.0/BpHwEffectBufferProviderCallback.h",
+        "android/hardware/audio/effect/2.0/BsEffectBufferProviderCallback.h",
+        "android/hardware/audio/effect/2.0/IEffectsFactory.h",
+        "android/hardware/audio/effect/2.0/IHwEffectsFactory.h",
+        "android/hardware/audio/effect/2.0/BnHwEffectsFactory.h",
+        "android/hardware/audio/effect/2.0/BpHwEffectsFactory.h",
+        "android/hardware/audio/effect/2.0/BsEffectsFactory.h",
+        "android/hardware/audio/effect/2.0/IEnvironmentalReverbEffect.h",
+        "android/hardware/audio/effect/2.0/IHwEnvironmentalReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwEnvironmentalReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwEnvironmentalReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BsEnvironmentalReverbEffect.h",
+        "android/hardware/audio/effect/2.0/IEqualizerEffect.h",
+        "android/hardware/audio/effect/2.0/IHwEqualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwEqualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwEqualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BsEqualizerEffect.h",
+        "android/hardware/audio/effect/2.0/ILoudnessEnhancerEffect.h",
+        "android/hardware/audio/effect/2.0/IHwLoudnessEnhancerEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwLoudnessEnhancerEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwLoudnessEnhancerEffect.h",
+        "android/hardware/audio/effect/2.0/BsLoudnessEnhancerEffect.h",
+        "android/hardware/audio/effect/2.0/INoiseSuppressionEffect.h",
+        "android/hardware/audio/effect/2.0/IHwNoiseSuppressionEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwNoiseSuppressionEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwNoiseSuppressionEffect.h",
+        "android/hardware/audio/effect/2.0/BsNoiseSuppressionEffect.h",
+        "android/hardware/audio/effect/2.0/IPresetReverbEffect.h",
+        "android/hardware/audio/effect/2.0/IHwPresetReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwPresetReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwPresetReverbEffect.h",
+        "android/hardware/audio/effect/2.0/BsPresetReverbEffect.h",
+        "android/hardware/audio/effect/2.0/IVirtualizerEffect.h",
+        "android/hardware/audio/effect/2.0/IHwVirtualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwVirtualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwVirtualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BsVirtualizerEffect.h",
+        "android/hardware/audio/effect/2.0/IVisualizerEffect.h",
+        "android/hardware/audio/effect/2.0/IHwVisualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BnHwVisualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BpHwVisualizerEffect.h",
+        "android/hardware/audio/effect/2.0/BsVisualizerEffect.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.audio.effect@2.0",
+    generated_sources: ["android.hardware.audio.effect@2.0_genc++"],
+    generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/audio/effect/2.0/Android.mk b/audio/effect/2.0/Android.mk
new file mode 100644
index 0000000..3383efd
--- /dev/null
+++ b/audio/effect/2.0/Android.mk
@@ -0,0 +1,53 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio.effect@2.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/audio/effect/V2_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IAcousticEchoCancelerEffect.hal
+$(GEN): $(LOCAL_PATH)/IAutomaticGainControlEffect.hal
+$(GEN): $(LOCAL_PATH)/IBassBoostEffect.hal
+$(GEN): $(LOCAL_PATH)/IDownmixEffect.hal
+$(GEN): $(LOCAL_PATH)/IEffect.hal
+$(GEN): $(LOCAL_PATH)/IEffectBufferProviderCallback.hal
+$(GEN): $(LOCAL_PATH)/IEffectsFactory.hal
+$(GEN): $(LOCAL_PATH)/IEnvironmentalReverbEffect.hal
+$(GEN): $(LOCAL_PATH)/IEqualizerEffect.hal
+$(GEN): $(LOCAL_PATH)/ILoudnessEnhancerEffect.hal
+$(GEN): $(LOCAL_PATH)/INoiseSuppressionEffect.hal
+$(GEN): $(LOCAL_PATH)/IPresetReverbEffect.hal
+$(GEN): $(LOCAL_PATH)/IVirtualizerEffect.hal
+$(GEN): $(LOCAL_PATH)/IVisualizerEffect.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.audio.effect@2.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/audio/effect/2.0/IAcousticEchoCancelerEffect.hal b/audio/effect/2.0/IAcousticEchoCancelerEffect.hal
new file mode 100644
index 0000000..9e2e0c3
--- /dev/null
+++ b/audio/effect/2.0/IAcousticEchoCancelerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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/2.0/IAutomaticGainControlEffect.hal b/audio/effect/2.0/IAutomaticGainControlEffect.hal
new file mode 100644
index 0000000..a02002d
--- /dev/null
+++ b/audio/effect/2.0/IAutomaticGainControlEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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/2.0/IBassBoostEffect.hal b/audio/effect/2.0/IBassBoostEffect.hal
new file mode 100644
index 0000000..bcf7b7d
--- /dev/null
+++ b/audio/effect/2.0/IBassBoostEffect.hal
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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/2.0/IDownmixEffect.hal b/audio/effect/2.0/IDownmixEffect.hal
new file mode 100644
index 0000000..06409a3
--- /dev/null
+++ b/audio/effect/2.0/IDownmixEffect.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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
+    };
+
+    setType(Type preset) generates (Result retval);
+
+    getType() generates (Result retval, Type preset);
+};
diff --git a/audio/effect/2.0/IEffect.hal b/audio/effect/2.0/IEffect.hal
new file mode 100644
index 0000000..9e10117
--- /dev/null
+++ b/audio/effect/2.0/IEffect.hal
@@ -0,0 +1,427 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.0;
+import IEffectBufferProviderCallback;
+
+interface IEffect {
+    /*
+     * Initialize effect engine--all configurations return to default.
+     *
+     * @return retval operation completion status.
+     */
+    @entry
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    reset() generates (Result retval);
+
+    /*
+     * Enable processing.
+     *
+     * @return retval operation completion status.
+     */
+    @callflow(next={"process"})
+    enable() generates (Result retval);
+
+    /*
+     * Disable processing.
+     *
+     * @return retval operation completion status.
+     */
+    @exit
+    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.
+     *
+     * @param device output device specification.
+     * @return retval operation completion status.
+     */
+    @callflow(next={"*"})
+    setDevice(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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     *
+     * @param device input device specification.
+     * @return retval operation completion status.
+     */
+    @callflow(next={"*"})
+    setInputDevice(AudioDevice device) generates (Result retval);
+
+    /*
+     * Read audio parameters configurations for input and output buffers.
+     *
+     * @return retval operation completion status.
+     * @return config configuration descriptor.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    setAuxChannelsConfig(EffectAuxChannelsConfig config)
+            generates (Result retval);
+
+    /*
+     * Set the audio source the capture path is configured for (Camcorder, voice
+     * recognition...).
+     *
+     * @param source source descriptor.
+     * @return retval operation completion status.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    offload(EffectOffloadParameter param) generates (Result retval);
+
+    /*
+     * Returns the effect descriptor.
+     *
+     * @return retval operation completion status.
+     * @return descriptor effect descriptor.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    @callflow(next={"*"})
+    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.
+     */
+    close() generates (Result retval);
+};
diff --git a/audio/effect/2.0/IEffectBufferProviderCallback.hal b/audio/effect/2.0/IEffectBufferProviderCallback.hal
new file mode 100644
index 0000000..545e2e5
--- /dev/null
+++ b/audio/effect/2.0/IEffectBufferProviderCallback.hal
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.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
+     */
+    // TODO(mnaganov): replace with FMQ version.
+    getBuffer() generates (AudioBuffer buffer);
+
+    /*
+     * Called to provide a buffer with the data written by 'process' function.
+     *
+     * @param buffer audio buffer for processing
+     */
+    // TODO(mnaganov): replace with FMQ version.
+    putBuffer(AudioBuffer buffer);
+};
diff --git a/audio/effect/2.0/IEffectsFactory.hal b/audio/effect/2.0/IEffectsFactory.hal
new file mode 100644
index 0000000..c82b4a2
--- /dev/null
+++ b/audio/effect/2.0/IEffectsFactory.hal
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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);
+
+    /*
+     * Dumps information about effects into the provided file descriptor.
+     * This is used for the dumpsys facility.
+     *
+     * @param fd dump file descriptor.
+     */
+    debugDump(handle fd);
+};
diff --git a/audio/effect/2.0/IEnvironmentalReverbEffect.hal b/audio/effect/2.0/IEnvironmentalReverbEffect.hal
new file mode 100644
index 0000000..d9b1ee6
--- /dev/null
+++ b/audio/effect/2.0/IEnvironmentalReverbEffect.hal
@@ -0,0 +1,178 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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 frequences level.
+     */
+    setRoomHfLevel(int16_t roomHfLevel) generates (Result retval);
+
+    /*
+     * Gets the room high frequences 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 frequences decay.
+     */
+    setDecayHfRatio(int16_t decayHfRatio) generates (Result retval);
+
+    /*
+     * Gets the ratio of high frequences 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/2.0/IEqualizerEffect.hal b/audio/effect/2.0/IEqualizerEffect.hal
new file mode 100644
index 0000000..afcc4b6
--- /dev/null
+++ b/audio/effect/2.0/IEqualizerEffect.hal
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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, uint16_t minLevel, uint16_t maxLevel);
+
+    /*
+     * Sets the gain for the given equalizer band.
+     */
+    setBandLevel(uint16_t band, uint16_t level) generates (Result retval);
+
+    /*
+     * Gets the gain for the given equalizer band.
+     */
+    getBandLevel(uint16_t band) generates (Result retval, uint16_t level);
+
+    /*
+     * Gets the center frequency of the given band.
+     */
+    getBandCenterFrequency(uint16_t band)
+            generates (Result retval, uint32_t centerFreq);
+
+    /*
+     * Gets the frequency range of the given frequency band.
+     */
+    getBandFrequencyRange(uint16_t band)
+            generates (Result retval, uint32_t minFreqHz, uint32_t maxFreqHz);
+
+    /*
+     * Gets the band that has the most effect on the given frequency.
+     */
+    getBandForFrequency(uint32_t freq) 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<uint16_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/2.0/ILoudnessEnhancerEffect.hal b/audio/effect/2.0/ILoudnessEnhancerEffect.hal
new file mode 100644
index 0000000..3e1ee4e
--- /dev/null
+++ b/audio/effect/2.0/ILoudnessEnhancerEffect.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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/2.0/INoiseSuppressionEffect.hal b/audio/effect/2.0/INoiseSuppressionEffect.hal
new file mode 100644
index 0000000..ae2bfb5
--- /dev/null
+++ b/audio/effect/2.0/INoiseSuppressionEffect.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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/2.0/IPresetReverbEffect.hal b/audio/effect/2.0/IPresetReverbEffect.hal
new file mode 100644
index 0000000..2237bc4
--- /dev/null
+++ b/audio/effect/2.0/IPresetReverbEffect.hal
@@ -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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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
+    };
+
+    setPreset(Preset preset) generates (Result retval);
+
+    getPreset() generates (Result retval, Preset preset);
+};
diff --git a/audio/effect/2.0/IVirtualizerEffect.hal b/audio/effect/2.0/IVirtualizerEffect.hal
new file mode 100644
index 0000000..2b7116c
--- /dev/null
+++ b/audio/effect/2.0/IVirtualizerEffect.hal
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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 {
+        AudioChannelMask mask; // speaker channel mask (1 bit set).
+        // 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(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/2.0/IVisualizerEffect.hal b/audio/effect/2.0/IVisualizerEffect.hal
new file mode 100644
index 0000000..79dc9ee
--- /dev/null
+++ b/audio/effect/2.0/IVisualizerEffect.hal
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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 lastest 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/2.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
new file mode 100644
index 0000000..7b9ca30
--- /dev/null
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AEC_Effect_HAL"
+#include <system/audio_effects/effect_aec.h>
+#include <android/log.h>
+
+#include "AcousticEchoCancelerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+AcousticEchoCancelerEffect::AcousticEchoCancelerEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+AcousticEchoCancelerEffect::~AcousticEchoCancelerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> AcousticEchoCancelerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> AcousticEchoCancelerEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AcousticEchoCancelerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> AcousticEchoCancelerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> AcousticEchoCancelerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> AcousticEchoCancelerEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> AcousticEchoCancelerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> AcousticEchoCancelerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> AcousticEchoCancelerEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> AcousticEchoCancelerEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> AcousticEchoCancelerEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> AcousticEchoCancelerEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> AcousticEchoCancelerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
+Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs)  {
+    return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs);
+}
+
+Return<void> AcousticEchoCancelerEffect::getEchoDelay(getEchoDelay_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(AEC_PARAM_ECHO_DELAY, _hidl_cb);
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
new file mode 100644
index 0000000..1ac925d
--- /dev/null
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ACOUSTICECHOCANCELEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ACOUSTICECHOCANCELEREFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IAcousticEchoCancelerEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect {
+    explicit AcousticEchoCancelerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
+    Return<Result> setEchoDelay(uint32_t echoDelayMs)  override;
+    Return<void> getEchoDelay(getEchoDelay_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~AcousticEchoCancelerEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ACOUSTICECHOCANCELEREFFECT_H
diff --git a/audio/effect/2.0/default/Android.mk b/audio/effect/2.0/default/Android.mk
new file mode 100644
index 0000000..18076ed
--- /dev/null
+++ b/audio/effect/2.0/default/Android.mk
@@ -0,0 +1,39 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.audio.effect@2.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    AcousticEchoCancelerEffect.cpp \
+    AudioBufferManager.cpp \
+    AutomaticGainControlEffect.cpp \
+    BassBoostEffect.cpp \
+    Conversions.cpp \
+    DownmixEffect.cpp \
+    Effect.cpp \
+    EffectsFactory.cpp \
+    EnvironmentalReverbEffect.cpp \
+    EqualizerEffect.cpp \
+    LoudnessEnhancerEffect.cpp \
+    NoiseSuppressionEffect.cpp \
+    PresetReverbEffect.cpp \
+    VirtualizerEffect.cpp \
+    VisualizerEffect.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    libeffects \
+    libfmq \
+    libhidlbase \
+    libhidlmemory \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    android.hardware.audio.common@2.0 \
+    android.hardware.audio.common@2.0-util \
+    android.hardware.audio.effect@2.0 \
+    android.hidl.memory@1.0 \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/effect/2.0/default/AudioBufferManager.cpp b/audio/effect/2.0/default/AudioBufferManager.cpp
new file mode 100644
index 0000000..603dbb8
--- /dev/null
+++ b/audio/effect/2.0/default/AudioBufferManager.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 <atomic>
+
+#include <hidlmemory/mapping.h>
+
+#include "AudioBufferManager.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager);
+
+bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper) {
+    // Check if we have this buffer already
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mBuffers.indexOfKey(buffer.id);
+    if (idx >= 0) {
+        *wrapper = mBuffers[idx].promote();
+        if (*wrapper != nullptr) return true;
+        mBuffers.removeItemsAt(idx);
+    }
+    // Need to create and init a new AudioBufferWrapper.
+    sp<AudioBufferWrapper> tempBuffer(new AudioBufferWrapper(buffer));
+    if (!tempBuffer->init()) return false;
+    *wrapper = tempBuffer;
+    mBuffers.add(buffer.id, *wrapper);
+    return true;
+}
+
+void AudioBufferManager::removeEntry(uint64_t id) {
+    std::lock_guard<std::mutex> lock(mLock);
+    ssize_t idx = mBuffers.indexOfKey(id);
+    if (idx >= 0) mBuffers.removeItemsAt(idx);
+}
+
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+AudioBufferWrapper::AudioBufferWrapper(const AudioBuffer& buffer) :
+        mHidlBuffer(buffer), mHalBuffer{ 0, { nullptr } } {
+}
+
+AudioBufferWrapper::~AudioBufferWrapper() {
+    AudioBufferManager::getInstance().removeEntry(mHidlBuffer.id);
+}
+
+bool AudioBufferWrapper::init() {
+    if (mHalBuffer.raw != nullptr) {
+        ALOGE("An attempt to init AudioBufferWrapper twice");
+        return false;
+    }
+    mHidlMemory = mapMemory(mHidlBuffer.data);
+    if (mHidlMemory == nullptr) {
+        ALOGE("Could not map HIDL memory to IMemory");
+        return false;
+    }
+    mHalBuffer.raw = static_cast<void*>(mHidlMemory->getPointer());
+    if (mHalBuffer.raw == nullptr) {
+        ALOGE("IMemory buffer pointer is null");
+        return false;
+    }
+    mHalBuffer.frameCount = mHidlBuffer.frameCount;
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/AudioBufferManager.h b/audio/effect/2.0/default/AudioBufferManager.h
new file mode 100644
index 0000000..6d65995
--- /dev/null
+++ b/audio/effect/2.0/default/AudioBufferManager.h
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_effect_V2_0_AudioBufferManager_H_
+#define android_hardware_audio_effect_V2_0_AudioBufferManager_H_
+
+#include <mutex>
+
+#include <android/hardware/audio/effect/2.0/types.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <system/audio_effect.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
+
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+class AudioBufferWrapper : public RefBase {
+  public:
+    explicit AudioBufferWrapper(const AudioBuffer& buffer);
+    virtual ~AudioBufferWrapper();
+    bool init();
+    audio_buffer_t* getHalBuffer() { return &mHalBuffer; }
+  private:
+    AudioBufferWrapper(const AudioBufferWrapper&) = delete;
+    void operator=(AudioBufferWrapper) = delete;
+
+    AudioBuffer mHidlBuffer;
+    sp<IMemory> mHidlMemory;
+    audio_buffer_t mHalBuffer;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+using ::android::hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
+
+namespace android {
+
+// This class needs to be in 'android' ns because Singleton macros require that.
+class AudioBufferManager : public Singleton<AudioBufferManager> {
+  public:
+    bool wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper);
+
+  private:
+    friend class hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
+
+    // Called by AudioBufferWrapper.
+    void removeEntry(uint64_t id);
+
+    std::mutex mLock;
+    KeyedVector<uint64_t, wp<AudioBufferWrapper>> mBuffers;
+};
+
+}  // namespace android
+
+#endif  // android_hardware_audio_effect_V2_0_AudioBufferManager_H_
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
new file mode 100644
index 0000000..62fe5f7
--- /dev/null
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AGC_Effect_HAL"
+#include <android/log.h>
+
+#include "AutomaticGainControlEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+AutomaticGainControlEffect::AutomaticGainControlEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+AutomaticGainControlEffect::~AutomaticGainControlEffect() {}
+
+void AutomaticGainControlEffect::propertiesFromHal(
+        const t_agc_settings& halProperties,
+        IAutomaticGainControlEffect::AllProperties* properties) {
+    properties->targetLevelMb = halProperties.targetLevel;
+    properties->compGainMb = halProperties.compGain;
+    properties->limiterEnabled = halProperties.limiterEnabled;
+}
+
+void AutomaticGainControlEffect::propertiesToHal(
+        const IAutomaticGainControlEffect::AllProperties& properties,
+        t_agc_settings* halProperties) {
+    halProperties->targetLevel = properties.targetLevelMb;
+    halProperties->compGain = properties.compGainMb;
+    halProperties->limiterEnabled = properties.limiterEnabled;
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> AutomaticGainControlEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> AutomaticGainControlEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AutomaticGainControlEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> AutomaticGainControlEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> AutomaticGainControlEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> AutomaticGainControlEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> AutomaticGainControlEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> AutomaticGainControlEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> AutomaticGainControlEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> AutomaticGainControlEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> AutomaticGainControlEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> AutomaticGainControlEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> AutomaticGainControlEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> AutomaticGainControlEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> AutomaticGainControlEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> AutomaticGainControlEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> AutomaticGainControlEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> AutomaticGainControlEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
+Return<Result> AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb)  {
+    return mEffect->setParam(AGC_PARAM_TARGET_LEVEL, targetLevelMb);
+}
+
+Return<void> AutomaticGainControlEffect::getTargetLevel(getTargetLevel_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(AGC_PARAM_TARGET_LEVEL, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setCompGain(int16_t compGainMb)  {
+    return mEffect->setParam(AGC_PARAM_COMP_GAIN, compGainMb);
+}
+
+Return<void> AutomaticGainControlEffect::getCompGain(getCompGain_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(AGC_PARAM_COMP_GAIN, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setLimiterEnabled(bool enabled)  {
+    return mEffect->setParam(AGC_PARAM_LIMITER_ENA, enabled);
+}
+
+Return<void> AutomaticGainControlEffect::isLimiterEnabled(isLimiterEnabled_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(AGC_PARAM_LIMITER_ENA, _hidl_cb);
+}
+
+Return<Result> AutomaticGainControlEffect::setAllProperties(const IAutomaticGainControlEffect::AllProperties& properties)  {
+    t_agc_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(AGC_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> AutomaticGainControlEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
+    t_agc_settings halProperties;
+    Result retval = mEffect->getParam(AGC_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.h b/audio/effect/2.0/default/AutomaticGainControlEffect.h
new file mode 100644
index 0000000..5e1f279
--- /dev/null
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.h
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
+
+#include <system/audio_effects/effect_agc.h>
+
+#include <android/hardware/audio/effect/2.0/IAutomaticGainControlEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct AutomaticGainControlEffect : public IAutomaticGainControlEffect {
+    explicit AutomaticGainControlEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
+    Return<Result> setTargetLevel(int16_t targetLevelMb)  override;
+    Return<void> getTargetLevel(getTargetLevel_cb _hidl_cb)  override;
+    Return<Result> setCompGain(int16_t compGainMb)  override;
+    Return<void> getCompGain(getCompGain_cb _hidl_cb)  override;
+    Return<Result> setLimiterEnabled(bool enabled)  override;
+    Return<void> isLimiterEnabled(isLimiterEnabled_cb _hidl_cb)  override;
+    Return<Result> setAllProperties(
+            const IAutomaticGainControlEffect::AllProperties& properties)  override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~AutomaticGainControlEffect();
+
+    void propertiesFromHal(
+            const t_agc_settings& halProperties,
+            IAutomaticGainControlEffect::AllProperties* properties);
+    void propertiesToHal(
+            const IAutomaticGainControlEffect::AllProperties& properties,
+            t_agc_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_AUTOMATICGAINCONTROLEFFECT_H
diff --git a/audio/effect/2.0/default/BassBoostEffect.cpp b/audio/effect/2.0/default/BassBoostEffect.cpp
new file mode 100644
index 0000000..8f35e5f
--- /dev/null
+++ b/audio/effect/2.0/default/BassBoostEffect.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BassBoost_HAL"
+#include <system/audio_effects/effect_bassboost.h>
+#include <android/log.h>
+
+#include "BassBoostEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+BassBoostEffect::BassBoostEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+BassBoostEffect::~BassBoostEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> BassBoostEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> BassBoostEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> BassBoostEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> BassBoostEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> BassBoostEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> BassBoostEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> BassBoostEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> BassBoostEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> BassBoostEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> BassBoostEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> BassBoostEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> BassBoostEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> BassBoostEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> BassBoostEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> BassBoostEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> BassBoostEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> BassBoostEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> BassBoostEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> BassBoostEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
+Return<void> BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb);
+}
+
+Return<Result> BassBoostEffect::setStrength(uint16_t strength)  {
+    return mEffect->setParam(BASSBOOST_PARAM_STRENGTH, strength);
+}
+
+Return<void> BassBoostEffect::getStrength(getStrength_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH, _hidl_cb);
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/BassBoostEffect.h b/audio/effect/2.0/default/BassBoostEffect.h
new file mode 100644
index 0000000..1e5053b
--- /dev/null
+++ b/audio/effect/2.0/default/BassBoostEffect.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_BASSBOOSTEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_BASSBOOSTEFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IBassBoostEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::effect::V2_0::IBassBoostEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct BassBoostEffect : public IBassBoostEffect {
+    explicit BassBoostEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
+    Return<void> isStrengthSupported(isStrengthSupported_cb _hidl_cb)  override;
+    Return<Result> setStrength(uint16_t strength)  override;
+    Return<void> getStrength(getStrength_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~BassBoostEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_BASSBOOSTEFFECT_H
diff --git a/audio/effect/2.0/default/Conversions.cpp b/audio/effect/2.0/default/Conversions.cpp
new file mode 100644
index 0000000..e7d4c46
--- /dev/null
+++ b/audio/effect/2.0/default/Conversions.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#include <memory.h>
+#include <stdio.h>
+
+#include "Conversions.h"
+#include "HidlUtils.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+void effectDescriptorFromHal(
+        const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor) {
+    HidlUtils::uuidFromHal(halDescriptor.type, &descriptor->type);
+    HidlUtils::uuidFromHal(halDescriptor.uuid, &descriptor->uuid);
+    descriptor->flags = EffectFlags(halDescriptor.flags);
+    descriptor->cpuLoad = halDescriptor.cpuLoad;
+    descriptor->memoryUsage = halDescriptor.memoryUsage;
+    memcpy(descriptor->name.data(), halDescriptor.name, descriptor->name.size());
+    memcpy(descriptor->implementor.data(),
+            halDescriptor.implementor, descriptor->implementor.size());
+}
+
+std::string uuidToString(const effect_uuid_t& halUuid) {
+    char str[64];
+    snprintf(str, sizeof(str), "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
+            halUuid.timeLow,
+            halUuid.timeMid,
+            halUuid.timeHiAndVersion,
+            halUuid.clockSeq,
+            halUuid.node[0],
+            halUuid.node[1],
+            halUuid.node[2],
+            halUuid.node[3],
+            halUuid.node[4],
+            halUuid.node[5]);
+    return str;
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/Conversions.h b/audio/effect/2.0/default/Conversions.h
new file mode 100644
index 0000000..7cef362
--- /dev/null
+++ b/audio/effect/2.0/default/Conversions.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_audio_effect_V2_0_Conversions_H_
+#define android_hardware_audio_effect_V2_0_Conversions_H_
+
+#include <string>
+
+#include <android/hardware/audio/effect/2.0/types.h>
+#include <system/audio_effect.h>
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+
+void effectDescriptorFromHal(
+        const effect_descriptor_t& halDescriptor, EffectDescriptor* descriptor);
+std::string uuidToString(const effect_uuid_t& halUuid);
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_audio_effect_V2_0_Conversions_H_
diff --git a/audio/effect/2.0/default/DownmixEffect.cpp b/audio/effect/2.0/default/DownmixEffect.cpp
new file mode 100644
index 0000000..92f15bd
--- /dev/null
+++ b/audio/effect/2.0/default/DownmixEffect.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Downmix_HAL"
+#include <system/audio_effects/effect_downmix.h>
+#include <android/log.h>
+
+#include "DownmixEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+DownmixEffect::DownmixEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+DownmixEffect::~DownmixEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> DownmixEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> DownmixEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> DownmixEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> DownmixEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> DownmixEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> DownmixEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> DownmixEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> DownmixEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> DownmixEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> DownmixEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> DownmixEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> DownmixEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> DownmixEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> DownmixEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> DownmixEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> DownmixEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> DownmixEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> DownmixEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> DownmixEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> DownmixEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> DownmixEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> DownmixEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> DownmixEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> DownmixEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
+Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset)  {
+    return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(preset));
+}
+
+Return<void> DownmixEffect::getType(getType_cb _hidl_cb)  {
+    downmix_type_t halPreset = DOWNMIX_TYPE_INVALID;
+    Result retval = mEffect->getParam(DOWNMIX_PARAM_TYPE, halPreset);
+    _hidl_cb(retval, Type(halPreset));
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/DownmixEffect.h b/audio/effect/2.0/default/DownmixEffect.h
new file mode 100644
index 0000000..125f34d
--- /dev/null
+++ b/audio/effect/2.0/default/DownmixEffect.h
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_DOWNMIXEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_DOWNMIXEFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IDownmixEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::effect::V2_0::IDownmixEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct DownmixEffect : public IDownmixEffect {
+    explicit DownmixEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
+    Return<Result> setType(IDownmixEffect::Type preset)  override;
+    Return<void> getType(getType_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~DownmixEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_DOWNMIXEFFECT_H
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
new file mode 100644
index 0000000..3c97fc4
--- /dev/null
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -0,0 +1,755 @@
+/*
+ * 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.
+ */
+
+#include <memory.h>
+
+#define LOG_TAG "EffectHAL"
+#include <android/log.h>
+#include <media/EffectsFactoryApi.h>
+
+#include "Conversions.h"
+#include "Effect.h"
+#include "EffectMap.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
+
+namespace {
+
+class ProcessThread : public Thread {
+  public:
+    // ProcessThread's lifespan never exceeds Effect's lifespan.
+    ProcessThread(std::atomic<bool>* stop,
+            effect_handle_t effect,
+            std::atomic<audio_buffer_t*>* inBuffer,
+            std::atomic<audio_buffer_t*>* outBuffer,
+            Effect::StatusMQ* statusMQ,
+            EventFlag* efGroup)
+            : Thread(false /*canCallJava*/),
+              mStop(stop),
+              mEffect(effect),
+              mHasProcessReverse((*mEffect)->process_reverse != NULL),
+              mInBuffer(inBuffer),
+              mOutBuffer(outBuffer),
+              mStatusMQ(statusMQ),
+              mEfGroup(efGroup) {
+    }
+    virtual ~ProcessThread() {}
+
+  private:
+    std::atomic<bool>* mStop;
+    effect_handle_t mEffect;
+    bool mHasProcessReverse;
+    std::atomic<audio_buffer_t*>* mInBuffer;
+    std::atomic<audio_buffer_t*>* mOutBuffer;
+    Effect::StatusMQ* mStatusMQ;
+    EventFlag* mEfGroup;
+
+    bool threadLoop() override;
+};
+
+bool ProcessThread::threadLoop() {
+    // This implementation doesn't return control back to the Thread until it decides to stop,
+    // as the Thread uses mutexes, and this can lead to priority inversion.
+    while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+        uint32_t efState = 0;
+        mEfGroup->wait(
+                static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL),
+                &efState,
+                NS_PER_SEC);
+        if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))) {
+            continue;  // Nothing to do.
+        }
+        Result retval = Result::OK;
+        if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE)
+                && !mHasProcessReverse) {
+            retval = Result::NOT_SUPPORTED;
+        }
+
+        if (retval == Result::OK) {
+            // affects both buffer pointers and their contents.
+            std::atomic_thread_fence(std::memory_order_acquire);
+            int32_t processResult;
+            audio_buffer_t* inBuffer =
+                    std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
+            audio_buffer_t* outBuffer =
+                    std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
+            if (inBuffer != nullptr && outBuffer != nullptr) {
+                if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
+                    processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
+                } else {
+                    processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
+                }
+                std::atomic_thread_fence(std::memory_order_release);
+            } else {
+                ALOGE("processing buffers were not set before calling 'process'");
+                processResult = -ENODEV;
+            }
+            switch(processResult) {
+                case 0: retval = Result::OK; break;
+                case -ENODATA: retval = Result::INVALID_STATE; break;
+                case -EINVAL: retval = Result::INVALID_ARGUMENTS; break;
+                default: retval = Result::NOT_INITIALIZED;
+            }
+        }
+        if (!mStatusMQ->write(&retval)) {
+            ALOGW("status message queue write failed");
+        }
+        mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
+    }
+
+    return false;
+}
+
+}  // namespace
+
+// static
+const char *Effect::sContextResultOfCommand = "returned status";
+const char *Effect::sContextCallToCommand = "error";
+const char *Effect::sContextCallFunction = sContextCallToCommand;
+
+Effect::Effect(effect_handle_t handle)
+        : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {
+}
+
+Effect::~Effect() {
+    close();
+}
+
+// static
+template<typename T> size_t Effect::alignedSizeIn(size_t s) {
+    return (s + sizeof(T) - 1) / sizeof(T);
+}
+
+// static
+template<typename T> std::unique_ptr<uint8_t[]> Effect::hidlVecToHal(
+        const hidl_vec<T>& vec, uint32_t* halDataSize) {
+    // Due to bugs in HAL, they may attempt to write into the provided
+    // input buffer. The original binder buffer is r/o, thus it is needed
+    // to create a r/w version.
+    *halDataSize = vec.size() * sizeof(T);
+    std::unique_ptr<uint8_t[]> halData(new uint8_t[*halDataSize]);
+    memcpy(&halData[0], &vec[0], *halDataSize);
+    return halData;
+}
+
+// static
+void Effect::effectAuxChannelsConfigFromHal(
+        const channel_config_t& halConfig, EffectAuxChannelsConfig* config) {
+    config->mainChannels = AudioChannelMask(halConfig.main_channels);
+    config->auxChannels = AudioChannelMask(halConfig.aux_channels);
+}
+
+// static
+void Effect::effectAuxChannelsConfigToHal(
+        const EffectAuxChannelsConfig& config, channel_config_t* halConfig) {
+    halConfig->main_channels = static_cast<audio_channel_mask_t>(config.mainChannels);
+    halConfig->aux_channels = static_cast<audio_channel_mask_t>(config.auxChannels);
+}
+
+// static
+void Effect::effectBufferConfigFromHal(
+        const buffer_config_t& halConfig, EffectBufferConfig* config) {
+    config->samplingRateHz = halConfig.samplingRate;
+    config->channels = AudioChannelMask(halConfig.channels);
+    config->format = AudioFormat(halConfig.format);
+    config->accessMode = EffectBufferAccess(halConfig.accessMode);
+    config->mask = EffectConfigParameters(halConfig.mask);
+}
+
+// static
+void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
+    // Note: setting the buffers directly is considered obsolete. They need to be set
+    // using 'setProcessBuffers'.
+    halConfig->buffer.frameCount = 0;
+    halConfig->buffer.raw = NULL;
+    halConfig->samplingRate = config.samplingRateHz;
+    halConfig->channels = static_cast<uint32_t>(config.channels);
+    // TODO(mnaganov): The framework code currently does not use BP, implement later.
+    halConfig->bufferProvider.cookie = NULL;
+    halConfig->bufferProvider.getBuffer = NULL;
+    halConfig->bufferProvider.releaseBuffer = NULL;
+    halConfig->format = static_cast<uint8_t>(config.format);
+    halConfig->accessMode = static_cast<uint8_t>(config.accessMode);
+    halConfig->mask = static_cast<uint8_t>(config.mask);
+}
+
+// static
+void Effect::effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config) {
+    effectBufferConfigFromHal(halConfig.inputCfg, &config->inputCfg);
+    effectBufferConfigFromHal(halConfig.outputCfg, &config->outputCfg);
+}
+
+// static
+void Effect::effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig) {
+    effectBufferConfigToHal(config.inputCfg, &halConfig->inputCfg);
+    effectBufferConfigToHal(config.outputCfg, &halConfig->outputCfg);
+}
+
+// static
+void Effect::effectOffloadParamToHal(
+        const EffectOffloadParameter& offload, effect_offload_param_t* halOffload) {
+    halOffload->isOffload = offload.isOffload;
+    halOffload->ioHandle = offload.ioHandle;
+}
+
+// static
+std::vector<uint8_t> Effect::parameterToHal(
+        uint32_t paramSize,
+        const void* paramData,
+        uint32_t valueSize,
+        const void** valueData) {
+    size_t valueOffsetFromData = alignedSizeIn<uint32_t>(paramSize) * sizeof(uint32_t);
+    size_t halParamBufferSize = sizeof(effect_param_t) + valueOffsetFromData + valueSize;
+    std::vector<uint8_t> halParamBuffer(halParamBufferSize, 0);
+    effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
+    halParam->psize = paramSize;
+    halParam->vsize = valueSize;
+    memcpy(halParam->data, paramData, paramSize);
+    if (valueData) {
+        if (*valueData) {
+            // Value data is provided.
+            memcpy(halParam->data + valueOffsetFromData, *valueData, valueSize);
+        } else {
+            // The caller needs the pointer to the value data location.
+            *valueData = halParam->data + valueOffsetFromData;
+        }
+    }
+    return halParamBuffer;
+}
+
+Result Effect::analyzeCommandStatus(const char* commandName, const char* context, status_t status) {
+    return analyzeStatus("command", commandName, context, status);
+}
+
+Result Effect::analyzeStatus(
+        const char* funcName,
+        const char* subFuncName,
+        const char* contextDescription,
+        status_t status) {
+    if (status != OK) {
+        ALOGW("Effect %p %s %s %s: %s",
+                mHandle, funcName, subFuncName, contextDescription, strerror(-status));
+    }
+    switch (status) {
+        case OK: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        case -ENOMEM: return Result::RESULT_TOO_BIG;
+        case -ENOSYS: return Result::NOT_SUPPORTED;
+        default: return Result::INVALID_STATE;
+    }
+}
+
+void Effect::getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb) {
+    uint32_t halResultSize = sizeof(effect_config_t);
+    effect_config_t halConfig;
+    status_t status = (*mHandle)->command(
+            mHandle, commandCode, 0, NULL, &halResultSize, &halConfig);
+    EffectConfig config;
+    if (status == OK) {
+        effectConfigFromHal(halConfig, &config);
+    }
+    cb(analyzeCommandStatus(commandName, sContextCallToCommand, status), config);
+}
+
+Result Effect::getCurrentConfigImpl(
+        uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess) {
+    uint32_t halCmd = featureId;
+    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configSize)];
+    memset(halResult, 0, sizeof(halResult));
+    uint32_t halResultSize = 0;
+    return sendCommandReturningStatusAndData(
+            EFFECT_CMD_GET_FEATURE_CONFIG, "GET_FEATURE_CONFIG",
+            sizeof(uint32_t), &halCmd,
+            &halResultSize, halResult,
+            sizeof(uint32_t),
+            [&]{ onSuccess(&halResult[1]); });
+}
+
+Result Effect::getParameterImpl(
+        uint32_t paramSize,
+        const void* paramData,
+        uint32_t valueSize,
+        GetParameterSuccessCallback onSuccess) {
+    // As it is unknown what method HAL uses for copying the provided parameter data,
+    // it is safer to make sure that input and output buffers do not overlap.
+    std::vector<uint8_t> halCmdBuffer =
+            parameterToHal(paramSize, paramData, valueSize, nullptr);
+    const void *valueData = nullptr;
+    std::vector<uint8_t> halParamBuffer =
+            parameterToHal(paramSize, paramData, valueSize, &valueData);
+    uint32_t halParamBufferSize = halParamBuffer.size();
+
+    return sendCommandReturningStatusAndData(
+            EFFECT_CMD_GET_PARAM, "GET_PARAM",
+            halCmdBuffer.size(), &halCmdBuffer[0],
+            &halParamBufferSize, &halParamBuffer[0],
+            sizeof(effect_param_t),
+            [&]{
+                effect_param_t *halParam = reinterpret_cast<effect_param_t*>(&halParamBuffer[0]);
+                onSuccess(halParam->vsize, valueData);
+            });
+}
+
+Result Effect::getSupportedConfigsImpl(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        GetSupportedConfigsSuccessCallback onSuccess) {
+    uint32_t halCmd[2] = { featureId, maxConfigs };
+    uint32_t halResultSize = 2 * sizeof(uint32_t) + maxConfigs * sizeof(configSize);
+    uint8_t halResult[halResultSize];
+    memset(&halResult[0], 0, halResultSize);
+    return sendCommandReturningStatusAndData(
+            EFFECT_CMD_GET_FEATURE_SUPPORTED_CONFIGS, "GET_FEATURE_SUPPORTED_CONFIGS",
+            sizeof(halCmd), halCmd,
+            &halResultSize, &halResult[0],
+            2 * sizeof(uint32_t),
+            [&]{
+                uint32_t *halResult32 = reinterpret_cast<uint32_t*>(&halResult[0]);
+                uint32_t supportedConfigs = *(++halResult32); // skip status field
+                if (supportedConfigs > maxConfigs) supportedConfigs = maxConfigs;
+                onSuccess(supportedConfigs, ++halResult32);
+            });
+}
+
+Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+    status_t status;
+    // Create message queue.
+    if (mStatusMQ) {
+        ALOGE("the client attempts to call prepareForProcessing_cb twice");
+        _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
+        return Void();
+    }
+    std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
+    if (!tempStatusMQ->isValid()) {
+        ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
+        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+        return Void();
+    }
+    status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
+    if (status != OK || !mEfGroup) {
+        ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+        return Void();
+    }
+
+    // Create and launch the thread.
+    mProcessThread = new ProcessThread(
+            &mStopProcessThread,
+            mHandle,
+            &mHalInBufferPtr,
+            &mHalOutBufferPtr,
+            tempStatusMQ.get(),
+            mEfGroup);
+    status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
+    if (status != OK) {
+        ALOGW("failed to start effect processing thread: %s", strerror(-status));
+        _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
+        return Void();
+    }
+
+    mStatusMQ = std::move(tempStatusMQ);
+    _hidl_cb(Result::OK, *mStatusMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Effect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    AudioBufferManager& manager = AudioBufferManager::getInstance();
+    sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
+    if (!manager.wrap(inBuffer, &tempInBuffer)) {
+        ALOGE("Could not map memory of the input buffer");
+        return Result::INVALID_ARGUMENTS;
+    }
+    if (!manager.wrap(outBuffer, &tempOutBuffer)) {
+        ALOGE("Could not map memory of the output buffer");
+        return Result::INVALID_ARGUMENTS;
+    }
+    mInBuffer = tempInBuffer;
+    mOutBuffer = tempOutBuffer;
+    // The processing thread only reads these pointers after waking up by an event flag,
+    // so it's OK to update the pair non-atomically.
+    mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
+    mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
+    return Result::OK;
+}
+
+Result Effect::sendCommand(int commandCode, const char* commandName) {
+    return sendCommand(commandCode, commandName, 0, NULL);
+}
+
+Result Effect::sendCommand(
+        int commandCode, const char* commandName, uint32_t size, void* data) {
+    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, 0, NULL);
+    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
+}
+
+Result Effect::sendCommandReturningData(
+        int commandCode, const char* commandName,
+        uint32_t* replySize, void* replyData) {
+    return sendCommandReturningData(commandCode, commandName, 0, NULL, replySize, replyData);
+}
+
+Result Effect::sendCommandReturningData(
+        int commandCode, const char* commandName,
+        uint32_t size, void* data,
+        uint32_t* replySize, void* replyData) {
+    uint32_t expectedReplySize = *replySize;
+    status_t status = (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+    if (status == OK && *replySize != expectedReplySize) {
+        status = -ENODATA;
+    }
+    return analyzeCommandStatus(commandName, sContextCallToCommand, status);
+}
+
+Result Effect::sendCommandReturningStatus(int commandCode, const char* commandName) {
+    return sendCommandReturningStatus(commandCode, commandName, 0, NULL);
+}
+
+Result Effect::sendCommandReturningStatus(
+        int commandCode, const char* commandName, uint32_t size, void* data) {
+    uint32_t replyCmdStatus;
+    uint32_t replySize = sizeof(uint32_t);
+    return sendCommandReturningStatusAndData(
+            commandCode, commandName, size, data, &replySize, &replyCmdStatus, replySize, []{});
+}
+
+Result Effect::sendCommandReturningStatusAndData(
+        int commandCode, const char* commandName,
+        uint32_t size, void* data,
+        uint32_t* replySize, void* replyData,
+        uint32_t minReplySize,
+        CommandSuccessCallback onSuccess) {
+    status_t status =
+            (*mHandle)->command(mHandle, commandCode, size, data, replySize, replyData);
+    Result retval;
+    if (status == OK && minReplySize >= sizeof(uint32_t) && *replySize >= minReplySize) {
+        uint32_t commandStatus = *reinterpret_cast<uint32_t*>(replyData);
+        retval = analyzeCommandStatus(commandName, sContextResultOfCommand, commandStatus);
+        if (commandStatus == OK) {
+            onSuccess();
+        }
+    } else {
+        retval = analyzeCommandStatus(commandName, sContextCallToCommand, status);
+    }
+    return retval;
+}
+
+Result Effect::setConfigImpl(
+        int commandCode, const char* commandName,
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    effect_config_t halConfig;
+    effectConfigToHal(config, &halConfig);
+    if (inputBufferProvider != 0) {
+        LOG_FATAL("Using input buffer provider is not supported");
+    }
+    if (outputBufferProvider != 0) {
+        LOG_FATAL("Using output buffer provider is not supported");
+    }
+    return sendCommandReturningStatus(
+            commandCode, commandName, sizeof(effect_config_t), &halConfig);
+}
+
+
+Result Effect::setParameterImpl(
+        uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData) {
+    std::vector<uint8_t> halParamBuffer = parameterToHal(
+            paramSize, paramData, valueSize, &valueData);
+    return sendCommandReturningStatus(
+            EFFECT_CMD_SET_PARAM, "SET_PARAM", halParamBuffer.size(), &halParamBuffer[0]);
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> Effect::init()  {
+    return sendCommandReturningStatus(EFFECT_CMD_INIT, "INIT");
+}
+
+Return<Result> Effect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider)  {
+    return setConfigImpl(
+            EFFECT_CMD_SET_CONFIG, "SET_CONFIG", config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> Effect::reset()  {
+    return sendCommand(EFFECT_CMD_RESET, "RESET");
+}
+
+Return<Result> Effect::enable()  {
+    return sendCommandReturningStatus(EFFECT_CMD_ENABLE, "ENABLE");
+}
+
+Return<Result> Effect::disable()  {
+    return sendCommandReturningStatus(EFFECT_CMD_DISABLE, "DISABLE");
+}
+
+Return<Result> Effect::setDevice(AudioDevice device)  {
+    uint32_t halDevice = static_cast<uint32_t>(device);
+    return sendCommand(EFFECT_CMD_SET_DEVICE, "SET_DEVICE", sizeof(uint32_t), &halDevice);
+}
+
+Return<void> Effect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
+    uint32_t halResultSize = halDataSize;
+    uint32_t halResult[volumes.size()];
+    Result retval = sendCommandReturningData(
+            EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
+            halDataSize, &halData[0],
+            &halResultSize, halResult);
+    hidl_vec<uint32_t> result;
+    if (retval == Result::OK) {
+        result.setToExternal(&halResult[0], halResultSize);
+    }
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(volumes, &halDataSize);
+    return sendCommand(
+            EFFECT_CMD_SET_VOLUME, "SET_VOLUME",
+            halDataSize, &halData[0]);
+}
+
+Return<Result> Effect::setAudioMode(AudioMode mode)  {
+    uint32_t halMode = static_cast<uint32_t>(mode);
+    return sendCommand(
+            EFFECT_CMD_SET_AUDIO_MODE, "SET_AUDIO_MODE", sizeof(uint32_t), &halMode);
+}
+
+Return<Result> Effect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider)  {
+    return setConfigImpl(EFFECT_CMD_SET_CONFIG_REVERSE, "SET_CONFIG_REVERSE",
+            config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> Effect::setInputDevice(AudioDevice device)  {
+    uint32_t halDevice = static_cast<uint32_t>(device);
+    return sendCommand(
+            EFFECT_CMD_SET_INPUT_DEVICE, "SET_INPUT_DEVICE", sizeof(uint32_t), &halDevice);
+}
+
+Return<void> Effect::getConfig(getConfig_cb _hidl_cb)  {
+    getConfigImpl(EFFECT_CMD_GET_CONFIG, "GET_CONFIG", _hidl_cb);
+    return Void();
+}
+
+Return<void> Effect::getConfigReverse(getConfigReverse_cb _hidl_cb)  {
+    getConfigImpl(EFFECT_CMD_GET_CONFIG_REVERSE, "GET_CONFIG_REVERSE", _hidl_cb);
+    return Void();
+}
+
+Return<void> Effect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  {
+    hidl_vec<EffectAuxChannelsConfig> result;
+    Result retval = getSupportedConfigsImpl(
+            EFFECT_FEATURE_AUX_CHANNELS,
+            maxConfigs,
+            sizeof(channel_config_t),
+            [&] (uint32_t supportedConfigs, void* configsData) {
+                result.resize(supportedConfigs);
+                channel_config_t *config = reinterpret_cast<channel_config_t*>(configsData);
+                for (size_t i = 0; i < result.size(); ++i) {
+                    effectAuxChannelsConfigFromHal(*config++, &result[i]);
+                }
+            });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<void> Effect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  {
+    uint32_t halCmd = EFFECT_FEATURE_AUX_CHANNELS;
+    uint32_t halResult[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
+    memset(halResult, 0, sizeof(halResult));
+    uint32_t halResultSize = 0;
+    EffectAuxChannelsConfig result;
+    Result retval = getCurrentConfigImpl(
+            EFFECT_FEATURE_AUX_CHANNELS,
+            sizeof(channel_config_t),
+            [&] (void* configData) {
+                effectAuxChannelsConfigFromHal(
+                        *reinterpret_cast<channel_config_t*>(configData), &result);
+            });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  {
+    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + sizeof(channel_config_t))];
+    halCmd[0] = EFFECT_FEATURE_AUX_CHANNELS;
+    effectAuxChannelsConfigToHal(config, reinterpret_cast<channel_config_t*>(&halCmd[1]));
+    return sendCommandReturningStatus(EFFECT_CMD_SET_FEATURE_CONFIG,
+            "SET_FEATURE_CONFIG AUX_CHANNELS", sizeof(halCmd), halCmd);
+}
+
+Return<Result> Effect::setAudioSource(AudioSource source)  {
+    uint32_t halSource = static_cast<uint32_t>(source);
+    return sendCommand(
+            EFFECT_CMD_SET_AUDIO_SOURCE, "SET_AUDIO_SOURCE", sizeof(uint32_t), &halSource);
+}
+
+Return<Result> Effect::offload(const EffectOffloadParameter& param)  {
+    effect_offload_param_t halParam;
+    effectOffloadParamToHal(param, &halParam);
+    return sendCommandReturningStatus(
+            EFFECT_CMD_OFFLOAD, "OFFLOAD", sizeof(effect_offload_param_t), &halParam);
+}
+
+Return<void> Effect::getDescriptor(getDescriptor_cb _hidl_cb)  {
+    effect_descriptor_t halDescriptor;
+    memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
+    status_t status = (*mHandle)->get_descriptor(mHandle, &halDescriptor);
+    EffectDescriptor descriptor;
+    if (status == OK) {
+        effectDescriptorFromHal(halDescriptor, &descriptor);
+    }
+    _hidl_cb(analyzeStatus("get_descriptor", "", sContextCallFunction, status), descriptor);
+    return Void();
+}
+
+Return<void> Effect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb)  {
+    uint32_t halDataSize;
+    std::unique_ptr<uint8_t[]> halData = hidlVecToHal(data, &halDataSize);
+    uint32_t halResultSize = resultMaxSize;
+    std::unique_ptr<uint8_t[]> halResult(new uint8_t[halResultSize]);
+    memset(&halResult[0], 0, halResultSize);
+
+    void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
+    void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
+    status_t status = (*mHandle)->command(
+            mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr);
+    hidl_vec<uint8_t> result;
+    if (status == OK && resultPtr != NULL) {
+        result.setToExternal(&halResult[0], halResultSize);
+    }
+    _hidl_cb(status, result);
+    return Void();
+}
+
+Return<Result> Effect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  {
+    return setParameterImpl(parameter.size(), &parameter[0], value.size(), &value[0]);
+}
+
+Return<void> Effect::getParameter(
+        const hidl_vec<uint8_t>& parameter, uint32_t valueMaxSize, getParameter_cb _hidl_cb)  {
+    hidl_vec<uint8_t> value;
+    Result retval = getParameterImpl(
+            parameter.size(),
+            &parameter[0],
+            valueMaxSize,
+            [&] (uint32_t valueSize, const void* valueData) {
+                value.setToExternal(
+                        reinterpret_cast<uint8_t*>(const_cast<void*>(valueData)), valueSize);
+            });
+    _hidl_cb(retval, value);
+    return Void();
+}
+
+Return<void> Effect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb)  {
+    uint32_t configCount = 0;
+    hidl_vec<uint8_t> result;
+    Result retval = getSupportedConfigsImpl(
+            featureId,
+            maxConfigs,
+            configSize,
+            [&] (uint32_t supportedConfigs, void* configsData) {
+                configCount = supportedConfigs;
+                result.resize(configCount * configSize);
+                memcpy(&result[0], configsData, result.size());
+            });
+    _hidl_cb(retval, configCount, result);
+    return Void();
+}
+
+Return<void> Effect::getCurrentConfigForFeature(
+        uint32_t featureId, uint32_t configSize, getCurrentConfigForFeature_cb _hidl_cb)  {
+    hidl_vec<uint8_t> result;
+    Result retval = getCurrentConfigImpl(
+            featureId,
+            configSize,
+            [&] (void* configData) {
+                result.resize(configSize);
+                memcpy(&result[0], configData, result.size());
+            });
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<Result> Effect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData)  {
+    uint32_t halCmd[alignedSizeIn<uint32_t>(sizeof(uint32_t) + configData.size())];
+    memset(halCmd, 0, sizeof(halCmd));
+    halCmd[0] = featureId;
+    memcpy(&halCmd[1], &configData[0], configData.size());
+    return sendCommandReturningStatus(
+            EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd);
+}
+
+Return<Result> Effect::close() {
+    if (mIsClosed) return Result::INVALID_STATE;
+    mIsClosed = true;
+    if (mProcessThread.get()) {
+        mStopProcessThread.store(true, std::memory_order_release);
+        status_t status = mProcessThread->requestExitAndWait();
+        ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
+    }
+    if (mEfGroup) {
+        status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+        ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
+    }
+    mInBuffer.clear();
+    mOutBuffer.clear();
+    int status = EffectRelease(mHandle);
+    ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+    EffectMap::getInstance().remove(mHandle);
+    mHandle = 0;
+    return Result::OK;
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/Effect.h b/audio/effect/2.0/default/Effect.h
new file mode 100644
index 0000000..13faec4
--- /dev/null
+++ b/audio/effect/2.0/default/Effect.h
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
+
+#include <atomic>
+#include <memory>
+#include <vector>
+
+#include <android/hardware/audio/effect/2.0/IEffect.h>
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
+
+#include <hardware/audio_effect.h>
+
+#include "AudioBufferManager.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectFeature;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Effect : public IEffect {
+    typedef MessageQueue<Result, kSynchronizedReadWrite> StatusMQ;
+
+    explicit Effect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Utility methods for extending interfaces.
+    template<typename T> Return<void> getIntegerParam(
+            uint32_t paramId, std::function<void(Result retval, T paramValue)> cb) {
+        T value;
+        Result retval = getParameterImpl(
+                sizeof(uint32_t), &paramId,
+                sizeof(T),
+                [&] (uint32_t valueSize, const void* valueData) {
+                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                    memcpy(&value, valueData, valueSize);
+                });
+        cb(retval, value);
+        return Void();
+    }
+
+    template<typename T> Result getParam(uint32_t paramId, T& paramValue) {
+        return getParameterImpl(
+                sizeof(uint32_t), &paramId,
+                sizeof(T),
+                [&] (uint32_t valueSize, const void* valueData) {
+                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                    memcpy(&paramValue, valueData, valueSize);
+                });
+    }
+
+    template<typename T> Result getParam(uint32_t paramId, uint32_t paramArg, T& paramValue) {
+        uint32_t params[2] = { paramId, paramArg };
+        return getParameterImpl(
+                sizeof(params), params,
+                sizeof(T),
+                [&] (uint32_t valueSize, const void* valueData) {
+                    if (valueSize > sizeof(T)) valueSize = sizeof(T);
+                    memcpy(&paramValue, valueData, valueSize);
+                });
+    }
+
+    template<typename T> Result setParam(uint32_t paramId, const T& paramValue) {
+        return setParameterImpl(sizeof(uint32_t), &paramId, sizeof(T), &paramValue);
+    }
+
+    template<typename T> Result setParam(uint32_t paramId, uint32_t paramArg, const T& paramValue) {
+        uint32_t params[2] = { paramId, paramArg };
+        return setParameterImpl(sizeof(params), params, sizeof(T), &paramValue);
+    }
+
+  private:
+    friend struct VirtualizerEffect;  // for getParameterImpl
+    friend struct VisualizerEffect;   // to allow executing commands
+
+    using CommandSuccessCallback = std::function<void()>;
+    using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>;
+    using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>;
+    using GetParameterSuccessCallback =
+            std::function<void(uint32_t valueSize, const void* valueData)>;
+    using GetSupportedConfigsSuccessCallback =
+            std::function<void(uint32_t supportedConfigs, void* configsData)>;
+
+    static const char *sContextResultOfCommand;
+    static const char *sContextCallToCommand;
+    static const char *sContextCallFunction;
+
+    bool mIsClosed;
+    effect_handle_t mHandle;
+    sp<AudioBufferWrapper> mInBuffer;
+    sp<AudioBufferWrapper> mOutBuffer;
+    std::atomic<audio_buffer_t*> mHalInBufferPtr;
+    std::atomic<audio_buffer_t*> mHalOutBufferPtr;
+    std::unique_ptr<StatusMQ> mStatusMQ;
+    EventFlag* mEfGroup;
+    std::atomic<bool> mStopProcessThread;
+    sp<Thread> mProcessThread;
+
+    virtual ~Effect();
+
+    template<typename T> static size_t alignedSizeIn(size_t s);
+    template<typename T> std::unique_ptr<uint8_t[]> hidlVecToHal(
+            const hidl_vec<T>& vec, uint32_t* halDataSize);
+    static void effectAuxChannelsConfigFromHal(
+            const channel_config_t& halConfig, EffectAuxChannelsConfig* config);
+    static void effectAuxChannelsConfigToHal(
+            const EffectAuxChannelsConfig& config, channel_config_t* halConfig);
+    static void effectBufferConfigFromHal(
+            const buffer_config_t& halConfig, EffectBufferConfig* config);
+    static void effectBufferConfigToHal(
+            const EffectBufferConfig& config, buffer_config_t* halConfig);
+    static void effectConfigFromHal(const effect_config_t& halConfig, EffectConfig* config);
+    static void effectConfigToHal(const EffectConfig& config, effect_config_t* halConfig);
+    static void effectOffloadParamToHal(
+            const EffectOffloadParameter& offload, effect_offload_param_t* halOffload);
+    static std::vector<uint8_t> parameterToHal(
+            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void** valueData);
+
+    Result analyzeCommandStatus(
+            const char* commandName, const char* context, status_t status);
+    Result analyzeStatus(
+            const char* funcName,
+            const char* subFuncName,
+            const char* contextDescription,
+            status_t status);
+    void getConfigImpl(int commandCode, const char* commandName, GetConfigCallback cb);
+    Result getCurrentConfigImpl(
+            uint32_t featureId, uint32_t configSize, GetCurrentConfigSuccessCallback onSuccess);
+    Result getParameterImpl(
+            uint32_t paramSize,
+            const void* paramData,
+            uint32_t valueSize,
+            GetParameterSuccessCallback onSuccess);
+    Result getSupportedConfigsImpl(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            GetSupportedConfigsSuccessCallback onSuccess);
+    Result sendCommand(int commandCode, const char* commandName);
+    Result sendCommand(int commandCode, const char* commandName, uint32_t size, void* data);
+    Result sendCommandReturningData(
+            int commandCode, const char* commandName, uint32_t* replySize, void* replyData);
+    Result sendCommandReturningData(
+            int commandCode, const char* commandName,
+            uint32_t size, void* data,
+            uint32_t* replySize, void* replyData);
+    Result sendCommandReturningStatus(int commandCode, const char* commandName);
+    Result sendCommandReturningStatus(
+            int commandCode, const char* commandName, uint32_t size, void* data);
+    Result sendCommandReturningStatusAndData(
+            int commandCode, const char* commandName,
+            uint32_t size, void* data,
+            uint32_t* replySize, void* replyData,
+            uint32_t minReplySize,
+            CommandSuccessCallback onSuccess);
+    Result setConfigImpl(
+            int commandCode, const char* commandName,
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider);
+    Result setParameterImpl(
+            uint32_t paramSize, const void* paramData, uint32_t valueSize, const void* valueData);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
diff --git a/audio/effect/2.0/default/EffectsFactory.cpp b/audio/effect/2.0/default/EffectsFactory.cpp
new file mode 100644
index 0000000..572a428
--- /dev/null
+++ b/audio/effect/2.0/default/EffectsFactory.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EffectFactoryHAL"
+#include <media/EffectsFactoryApi.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_agc.h>
+#include <system/audio_effects/effect_bassboost.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_environmentalreverb.h>
+#include <system/audio_effects/effect_equalizer.h>
+#include <system/audio_effects/effect_loudnessenhancer.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_presetreverb.h>
+#include <system/audio_effects/effect_virtualizer.h>
+#include <system/audio_effects/effect_visualizer.h>
+#include <android/log.h>
+
+#include "AcousticEchoCancelerEffect.h"
+#include "AutomaticGainControlEffect.h"
+#include "BassBoostEffect.h"
+#include "Conversions.h"
+#include "DownmixEffect.h"
+#include "EffectsFactory.h"
+#include "HidlUtils.h"
+#include "Effect.h"
+#include "EffectMap.h"
+#include "EnvironmentalReverbEffect.h"
+#include "EqualizerEffect.h"
+#include "LoudnessEnhancerEffect.h"
+#include "NoiseSuppressionEffect.h"
+#include "PresetReverbEffect.h"
+#include "VirtualizerEffect.h"
+#include "VisualizerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+// static
+sp<IEffect> EffectsFactory::dispatchEffectInstanceCreation(
+        const effect_descriptor_t& halDescriptor, effect_handle_t handle) {
+    const effect_uuid_t *halUuid = &halDescriptor.type;
+    if (memcmp(halUuid, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) {
+        return new AcousticEchoCancelerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_AGC, sizeof(effect_uuid_t)) == 0) {
+        return new AutomaticGainControlEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_BASSBOOST, sizeof(effect_uuid_t)) == 0) {
+        return new BassBoostEffect(handle);
+    } else if (memcmp(halUuid, EFFECT_UIID_DOWNMIX, sizeof(effect_uuid_t)) == 0) {
+        return new DownmixEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_ENVIRONMENTALREVERB, sizeof(effect_uuid_t)) == 0) {
+        return new EnvironmentalReverbEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_EQUALIZER, sizeof(effect_uuid_t)) == 0) {
+        return new EqualizerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_LOUDNESS_ENHANCER, sizeof(effect_uuid_t)) == 0) {
+        return new LoudnessEnhancerEffect(handle);
+    } else if (memcmp(halUuid, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
+        return new NoiseSuppressionEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_PRESETREVERB, sizeof(effect_uuid_t)) == 0) {
+        return new PresetReverbEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_VIRTUALIZER, sizeof(effect_uuid_t)) == 0) {
+        return new VirtualizerEffect(handle);
+    } else if (memcmp(halUuid, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) {
+        return new VisualizerEffect(handle);
+    }
+    return new Effect(handle);
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffectsFactory follow.
+Return<void> EffectsFactory::getAllDescriptors(getAllDescriptors_cb _hidl_cb)  {
+    Result retval(Result::OK);
+    hidl_vec<EffectDescriptor> result;
+    uint32_t numEffects;
+    status_t status;
+
+restart:
+    numEffects = 0;
+    status = EffectQueryNumberEffects(&numEffects);
+    if (status != OK) {
+        retval = Result::NOT_INITIALIZED;
+        ALOGW("Error querying number of effects: %s", strerror(-status));
+        goto exit;
+    }
+    result.resize(numEffects);
+    for (uint32_t i = 0; i < numEffects; ++i) {
+        effect_descriptor_t halDescriptor;
+        status = EffectQueryEffect(i, &halDescriptor);
+        if (status == OK) {
+            effectDescriptorFromHal(halDescriptor, &result[i]);
+        } else {
+            ALOGW("Error querying effect at position %d / %d: %s",
+                    i, numEffects, strerror(-status));
+            switch (status) {
+                case -ENOSYS: {
+                    // Effect list has changed.
+                    goto restart;
+                }
+                case -ENOENT: {
+                    // No more effects available.
+                    result.resize(i);
+                }
+                default: {
+                    result.resize(0);
+                    retval = Result::NOT_INITIALIZED;
+                }
+            }
+            break;
+        }
+    }
+
+exit:
+    _hidl_cb(retval, result);
+    return Void();
+}
+
+Return<void> EffectsFactory::getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb)  {
+    effect_uuid_t halUuid;
+    HidlUtils::uuidToHal(uid, &halUuid);
+    effect_descriptor_t halDescriptor;
+    status_t status = EffectGetDescriptor(&halUuid, &halDescriptor);
+    EffectDescriptor descriptor;
+    effectDescriptorFromHal(halDescriptor, &descriptor);
+    Result retval(Result::OK);
+    if (status != OK) {
+        ALOGW("Error querying effect descriptor for %s: %s",
+                uuidToString(halUuid).c_str(), strerror(-status));
+        if (status == -ENOENT) {
+            retval = Result::INVALID_ARGUMENTS;
+        } else {
+            retval = Result::NOT_INITIALIZED;
+        }
+    }
+    _hidl_cb(retval, descriptor);
+    return Void();
+}
+
+Return<void> EffectsFactory::createEffect(
+        const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb)  {
+    effect_uuid_t halUuid;
+    HidlUtils::uuidToHal(uid, &halUuid);
+    effect_handle_t handle;
+    Result retval(Result::OK);
+    status_t status = EffectCreate(&halUuid, session, ioHandle, &handle);
+    sp<IEffect> effect;
+    uint64_t effectId = EffectMap::INVALID_ID;
+    if (status == OK) {
+        effect_descriptor_t halDescriptor;
+        memset(&halDescriptor, 0, sizeof(effect_descriptor_t));
+        status = (*handle)->get_descriptor(handle, &halDescriptor);
+        if (status == OK) {
+            effect = dispatchEffectInstanceCreation(halDescriptor, handle);
+            effectId = EffectMap::getInstance().add(handle);
+        } else {
+            EffectRelease(handle);
+        }
+    }
+    if (status != OK) {
+        ALOGW("Error creating effect %s: %s", uuidToString(halUuid).c_str(), strerror(-status));
+        if (status == -ENOENT) {
+            retval = Result::INVALID_ARGUMENTS;
+        } else {
+            retval = Result::NOT_INITIALIZED;
+        }
+    }
+    _hidl_cb(retval, effect, effectId);
+    return Void();
+}
+
+Return<void> EffectsFactory::debugDump(const hidl_handle& fd)  {
+    if (fd->numFds == 1) {
+        EffectDumpEffects(fd->data[0]);
+    }
+    return Void();
+}
+
+
+IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* /* name */) {
+    return new EffectsFactory();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/EffectsFactory.h b/audio/effect/2.0/default/EffectsFactory.h
new file mode 100644
index 0000000..829a534
--- /dev/null
+++ b/audio/effect/2.0/default/EffectsFactory.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECTSFACTORY_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECTSFACTORY_H
+
+#include <system/audio_effect.h>
+
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectsFactory;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EffectsFactory : public IEffectsFactory {
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffectsFactory follow.
+    Return<void> getAllDescriptors(getAllDescriptors_cb _hidl_cb)  override;
+    Return<void> getDescriptor(const Uuid& uid, getDescriptor_cb _hidl_cb)  override;
+    Return<void> createEffect(
+            const Uuid& uid, int32_t session, int32_t ioHandle, createEffect_cb _hidl_cb)  override;
+    Return<void> debugDump(const hidl_handle& fd)  override;
+
+  private:
+    static sp<IEffect> dispatchEffectInstanceCreation(
+            const effect_descriptor_t& halDescriptor, effect_handle_t handle);
+};
+
+extern "C" IEffectsFactory* HIDL_FETCH_IEffectsFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECTSFACTORY_H
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
new file mode 100644
index 0000000..86ff368
--- /dev/null
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
@@ -0,0 +1,316 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "EnvReverb_HAL"
+#include <android/log.h>
+
+#include "EnvironmentalReverbEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+EnvironmentalReverbEffect::EnvironmentalReverbEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+EnvironmentalReverbEffect::~EnvironmentalReverbEffect() {}
+
+void EnvironmentalReverbEffect::propertiesFromHal(
+        const t_reverb_settings& halProperties,
+        IEnvironmentalReverbEffect::AllProperties* properties) {
+    properties->roomLevel = halProperties.roomLevel;
+    properties->roomHfLevel = halProperties.roomHFLevel;
+    properties->decayTime = halProperties.decayTime;
+    properties->decayHfRatio = halProperties.decayHFRatio;
+    properties->reflectionsLevel = halProperties.reflectionsLevel;
+    properties->reflectionsDelay = halProperties.reflectionsDelay;
+    properties->reverbLevel = halProperties.reverbLevel;
+    properties->reverbDelay = halProperties.reverbDelay;
+    properties->diffusion = halProperties.diffusion;
+    properties->density = halProperties.density;
+}
+
+void EnvironmentalReverbEffect::propertiesToHal(
+        const IEnvironmentalReverbEffect::AllProperties& properties,
+        t_reverb_settings* halProperties) {
+    halProperties->roomLevel = properties.roomLevel;
+    halProperties->roomHFLevel = properties.roomHfLevel;
+    halProperties->decayTime = properties.decayTime;
+    halProperties->decayHFRatio = properties.decayHfRatio;
+    halProperties->reflectionsLevel = properties.reflectionsLevel;
+    halProperties->reflectionsDelay = properties.reflectionsDelay;
+    halProperties->reverbLevel = properties.reverbLevel;
+    halProperties->reverbDelay = properties.reverbDelay;
+    halProperties->diffusion = properties.diffusion;
+    halProperties->density = properties.density;
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> EnvironmentalReverbEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> EnvironmentalReverbEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EnvironmentalReverbEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> EnvironmentalReverbEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> EnvironmentalReverbEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> EnvironmentalReverbEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> EnvironmentalReverbEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> EnvironmentalReverbEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EnvironmentalReverbEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> EnvironmentalReverbEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> EnvironmentalReverbEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> EnvironmentalReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> EnvironmentalReverbEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> EnvironmentalReverbEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> EnvironmentalReverbEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> EnvironmentalReverbEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
+Return<Result> EnvironmentalReverbEffect::setBypass(bool bypass)  {
+    return mEffect->setParam(REVERB_PARAM_BYPASS, bypass);
+}
+
+Return<void> EnvironmentalReverbEffect::getBypass(getBypass_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_BYPASS, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setRoomLevel(int16_t roomLevel)  {
+    return mEffect->setParam(REVERB_PARAM_ROOM_LEVEL, roomLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getRoomLevel(getRoomLevel_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setRoomHfLevel(int16_t roomHfLevel)  {
+    return mEffect->setParam(REVERB_PARAM_ROOM_HF_LEVEL, roomHfLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getRoomHfLevel(getRoomHfLevel_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_ROOM_HF_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDecayTime(uint32_t decayTime)  {
+    return mEffect->setParam(REVERB_PARAM_DECAY_TIME, decayTime);
+}
+
+Return<void> EnvironmentalReverbEffect::getDecayTime(getDecayTime_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_TIME, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDecayHfRatio(int16_t decayHfRatio)  {
+    return mEffect->setParam(REVERB_PARAM_DECAY_HF_RATIO, decayHfRatio);
+}
+
+Return<void> EnvironmentalReverbEffect::getDecayHfRatio(getDecayHfRatio_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_DECAY_HF_RATIO, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReflectionsLevel(int16_t reflectionsLevel)  {
+    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_LEVEL, reflectionsLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getReflectionsLevel(getReflectionsLevel_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReflectionsDelay(uint32_t reflectionsDelay)  {
+    return mEffect->setParam(REVERB_PARAM_REFLECTIONS_DELAY, reflectionsDelay);
+}
+
+Return<void> EnvironmentalReverbEffect::getReflectionsDelay(getReflectionsDelay_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_REFLECTIONS_DELAY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReverbLevel(int16_t reverbLevel)  {
+    return mEffect->setParam(REVERB_PARAM_REVERB_LEVEL, reverbLevel);
+}
+
+Return<void> EnvironmentalReverbEffect::getReverbLevel(getReverbLevel_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_LEVEL, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setReverbDelay(uint32_t reverbDelay) {
+    return mEffect->setParam(REVERB_PARAM_REVERB_DELAY, reverbDelay);
+}
+
+Return<void> EnvironmentalReverbEffect::getReverbDelay(getReverbDelay_cb _hidl_cb) {
+    return mEffect->getIntegerParam(REVERB_PARAM_REVERB_DELAY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDiffusion(int16_t diffusion)  {
+    return mEffect->setParam(REVERB_PARAM_DIFFUSION, diffusion);
+}
+
+Return<void> EnvironmentalReverbEffect::getDiffusion(getDiffusion_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_DIFFUSION, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setDensity(int16_t density)  {
+    return mEffect->setParam(REVERB_PARAM_DENSITY, density);
+}
+
+Return<void> EnvironmentalReverbEffect::getDensity(getDensity_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(REVERB_PARAM_DENSITY, _hidl_cb);
+}
+
+Return<Result> EnvironmentalReverbEffect::setAllProperties(
+        const IEnvironmentalReverbEffect::AllProperties& properties)  {
+    t_reverb_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(REVERB_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> EnvironmentalReverbEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
+    t_reverb_settings halProperties;
+    Result retval = mEffect->getParam(REVERB_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.h b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
new file mode 100644
index 0000000..794caac
--- /dev/null
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ENVIRONMENTALREVERBEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ENVIRONMENTALREVERBEFFECT_H
+
+#include <system/audio_effects/effect_environmentalreverb.h>
+
+#include <android/hardware/audio/effect/2.0/IEnvironmentalReverbEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EnvironmentalReverbEffect : public IEnvironmentalReverbEffect {
+    explicit EnvironmentalReverbEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
+    Return<Result> setBypass(bool bypass)  override;
+    Return<void> getBypass(getBypass_cb _hidl_cb)  override;
+    Return<Result> setRoomLevel(int16_t roomLevel)  override;
+    Return<void> getRoomLevel(getRoomLevel_cb _hidl_cb)  override;
+    Return<Result> setRoomHfLevel(int16_t roomHfLevel)  override;
+    Return<void> getRoomHfLevel(getRoomHfLevel_cb _hidl_cb)  override;
+    Return<Result> setDecayTime(uint32_t decayTime)  override;
+    Return<void> getDecayTime(getDecayTime_cb _hidl_cb)  override;
+    Return<Result> setDecayHfRatio(int16_t decayHfRatio)  override;
+    Return<void> getDecayHfRatio(getDecayHfRatio_cb _hidl_cb)  override;
+    Return<Result> setReflectionsLevel(int16_t reflectionsLevel)  override;
+    Return<void> getReflectionsLevel(getReflectionsLevel_cb _hidl_cb)  override;
+    Return<Result> setReflectionsDelay(uint32_t reflectionsDelay)  override;
+    Return<void> getReflectionsDelay(getReflectionsDelay_cb _hidl_cb)  override;
+    Return<Result> setReverbLevel(int16_t reverbLevel)  override;
+    Return<void> getReverbLevel(getReverbLevel_cb _hidl_cb)  override;
+    Return<Result> setReverbDelay(uint32_t reverbDelay)  override;
+    Return<void> getReverbDelay(getReverbDelay_cb _hidl_cb)  override;
+    Return<Result> setDiffusion(int16_t diffusion)  override;
+    Return<void> getDiffusion(getDiffusion_cb _hidl_cb)  override;
+    Return<Result> setDensity(int16_t density)  override;
+    Return<void> getDensity(getDensity_cb _hidl_cb)  override;
+    Return<Result> setAllProperties(
+            const IEnvironmentalReverbEffect::AllProperties& properties)  override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~EnvironmentalReverbEffect();
+
+    void propertiesFromHal(
+            const t_reverb_settings& halProperties,
+            IEnvironmentalReverbEffect::AllProperties* properties);
+    void propertiesToHal(
+            const IEnvironmentalReverbEffect::AllProperties& properties,
+            t_reverb_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_ENVIRONMENTALREVERBEFFECT_H
diff --git a/audio/effect/2.0/default/EqualizerEffect.cpp b/audio/effect/2.0/default/EqualizerEffect.cpp
new file mode 100644
index 0000000..223716c
--- /dev/null
+++ b/audio/effect/2.0/default/EqualizerEffect.cpp
@@ -0,0 +1,292 @@
+/*
+ * 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.
+ */
+
+#include <memory.h>
+
+#define LOG_TAG "Equalizer_HAL"
+#include <android/log.h>
+
+#include "EqualizerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+EqualizerEffect::EqualizerEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+EqualizerEffect::~EqualizerEffect() {}
+
+void EqualizerEffect::propertiesFromHal(
+        t_equalizer_settings& halProperties,
+        IEqualizerEffect::AllProperties* properties) {
+    properties->curPreset = halProperties.curPreset;
+    properties->bandLevels.setToExternal(&halProperties.bandLevels[0], halProperties.numBands);
+}
+
+std::vector<uint8_t> EqualizerEffect::propertiesToHal(
+        const IEqualizerEffect::AllProperties& properties,
+        t_equalizer_settings** halProperties) {
+    size_t bandsSize = properties.bandLevels.size() * sizeof(uint16_t);
+    std::vector<uint8_t> halBuffer(sizeof(t_equalizer_settings) + bandsSize, 0);
+    *halProperties = reinterpret_cast<t_equalizer_settings*>(&halBuffer[0]);
+    (*halProperties)->curPreset = properties.curPreset;
+    (*halProperties)->numBands = properties.bandLevels.size();
+    memcpy((*halProperties)->bandLevels, &properties.bandLevels[0], bandsSize);
+    return halBuffer;
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> EqualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> EqualizerEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EqualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> EqualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> EqualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> EqualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> EqualizerEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> EqualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> EqualizerEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> EqualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> EqualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> EqualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> EqualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> EqualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> EqualizerEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> EqualizerEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> EqualizerEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> EqualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
+Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(EQ_PARAM_NUM_BANDS, _hidl_cb);
+}
+
+Return<void> EqualizerEffect::getLevelRange(getLevelRange_cb _hidl_cb)  {
+    uint16_t halLevels[2] = { 0, 0 };
+    Result retval = mEffect->getParam(EQ_PARAM_LEVEL_RANGE, halLevels);
+    _hidl_cb(retval, halLevels[0], halLevels[1]);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setBandLevel(uint16_t band, uint16_t level)  {
+    return mEffect->setParam(EQ_PARAM_BAND_LEVEL, band, level);
+}
+
+Return<void> EqualizerEffect::getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  {
+    uint16_t halLevel = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_BAND_LEVEL, band, halLevel);
+    _hidl_cb(retval, halLevel);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandCenterFrequency(
+        uint16_t band, getBandCenterFrequency_cb _hidl_cb)  {
+    uint32_t halFreq = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_CENTER_FREQ, band, halFreq);
+    _hidl_cb(retval, halFreq);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandFrequencyRange(
+        uint16_t band, getBandFrequencyRange_cb _hidl_cb)  {
+    uint32_t halFreqs[2] = { 0, 0 };
+    Result retval = mEffect->getParam(EQ_PARAM_BAND_FREQ_RANGE, band, halFreqs);
+    _hidl_cb(retval, halFreqs[0], halFreqs[1]);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb)  {
+    uint16_t halBand = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_GET_BAND, freq, halBand);
+    _hidl_cb(retval, halBand);
+    return Void();
+}
+
+Return<void> EqualizerEffect::getPresetNames(getPresetNames_cb _hidl_cb)  {
+    uint16_t halPresetCount = 0;
+    Result retval = mEffect->getParam(EQ_PARAM_GET_NUM_OF_PRESETS, halPresetCount);
+    hidl_vec<hidl_string> presetNames;
+    if (retval == Result::OK) {
+        presetNames.resize(halPresetCount);
+        for (uint16_t i = 0; i < halPresetCount; ++i) {
+            char halPresetName[EFFECT_STRING_LEN_MAX];
+            retval = mEffect->getParam(EQ_PARAM_GET_PRESET_NAME, i, halPresetName);
+            if (retval == Result::OK) {
+                presetNames[i] = halPresetName;
+            } else {
+                presetNames.resize(i);
+            }
+        }
+    }
+    _hidl_cb(retval, presetNames);
+    return Void();
+}
+
+Return<Result> EqualizerEffect::setCurrentPreset(uint16_t preset)  {
+    return mEffect->setParam(EQ_PARAM_CUR_PRESET, preset);
+}
+
+Return<void> EqualizerEffect::getCurrentPreset(getCurrentPreset_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(EQ_PARAM_CUR_PRESET, _hidl_cb);
+}
+
+Return<Result> EqualizerEffect::setAllProperties(
+        const IEqualizerEffect::AllProperties& properties)  {
+    t_equalizer_settings *halPropertiesPtr = nullptr;
+    std::vector<uint8_t> halBuffer = propertiesToHal(properties, &halPropertiesPtr);
+    return mEffect->setParam(EQ_PARAM_PROPERTIES, *halPropertiesPtr);
+}
+
+Return<void> EqualizerEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
+    t_equalizer_settings halProperties;
+    Result retval = mEffect->getParam(EQ_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/EqualizerEffect.h b/audio/effect/2.0/default/EqualizerEffect.h
new file mode 100644
index 0000000..c9bed4f
--- /dev/null
+++ b/audio/effect/2.0/default/EqualizerEffect.h
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
+
+#include <vector>
+
+#include <system/audio_effects/effect_equalizer.h>
+
+#include <android/hardware/audio/effect/2.0/IEqualizerEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::IEqualizerEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct EqualizerEffect : public IEqualizerEffect {
+    explicit EqualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
+    Return<void> getNumBands(getNumBands_cb _hidl_cb)  override;
+    Return<void> getLevelRange(getLevelRange_cb _hidl_cb)  override;
+    Return<Result> setBandLevel(uint16_t band, uint16_t level)  override;
+    Return<void> getBandLevel(uint16_t band, getBandLevel_cb _hidl_cb)  override;
+    Return<void> getBandCenterFrequency(
+            uint16_t band, getBandCenterFrequency_cb _hidl_cb)  override;
+    Return<void> getBandFrequencyRange(uint16_t band, getBandFrequencyRange_cb _hidl_cb)  override;
+    Return<void> getBandForFrequency(uint32_t freq, getBandForFrequency_cb _hidl_cb)  override;
+    Return<void> getPresetNames(getPresetNames_cb _hidl_cb)  override;
+    Return<Result> setCurrentPreset(uint16_t preset)  override;
+    Return<void> getCurrentPreset(getCurrentPreset_cb _hidl_cb)  override;
+    Return<Result> setAllProperties(const IEqualizerEffect::AllProperties& properties)  override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~EqualizerEffect();
+
+    void propertiesFromHal(
+            t_equalizer_settings& halProperties,
+            IEqualizerEffect::AllProperties* properties);
+    std::vector<uint8_t> propertiesToHal(
+            const IEqualizerEffect::AllProperties& properties,
+            t_equalizer_settings** halProperties);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EQUALIZEREFFECT_H
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
new file mode 100644
index 0000000..e58b42c
--- /dev/null
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+#include <system/audio_effects/effect_loudnessenhancer.h>
+
+#define LOG_TAG "LoudnessEnhancer_HAL"
+#include <system/audio_effects/effect_aec.h>
+#include <android/log.h>
+
+#include "LoudnessEnhancerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+LoudnessEnhancerEffect::LoudnessEnhancerEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+LoudnessEnhancerEffect::~LoudnessEnhancerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> LoudnessEnhancerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> LoudnessEnhancerEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> LoudnessEnhancerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> LoudnessEnhancerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> LoudnessEnhancerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> LoudnessEnhancerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> LoudnessEnhancerEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> LoudnessEnhancerEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> LoudnessEnhancerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> LoudnessEnhancerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> LoudnessEnhancerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> LoudnessEnhancerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> LoudnessEnhancerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> LoudnessEnhancerEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> LoudnessEnhancerEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> LoudnessEnhancerEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> LoudnessEnhancerEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> LoudnessEnhancerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
+Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb)  {
+    return mEffect->setParam(LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB, targetGainMb);
+}
+
+Return<void> LoudnessEnhancerEffect::getTargetGain(getTargetGain_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(LOUDNESS_ENHANCER_DEFAULT_TARGET_GAIN_MB, _hidl_cb);
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.h b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
new file mode 100644
index 0000000..039b8d6
--- /dev/null
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_LOUDNESSENHANCEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_LOUDNESSENHANCEREFFECT_H
+
+#include <android/hardware/audio/effect/2.0/ILoudnessEnhancerEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct LoudnessEnhancerEffect : public ILoudnessEnhancerEffect {
+    explicit LoudnessEnhancerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
+    Return<Result> setTargetGain(int32_t targetGainMb)  override;
+    Return<void> getTargetGain(getTargetGain_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~LoudnessEnhancerEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_LOUDNESSENHANCEREFFECT_H
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
new file mode 100644
index 0000000..7c4e06d
--- /dev/null
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "NS_Effect_HAL"
+#include <android/log.h>
+
+#include "NoiseSuppressionEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+NoiseSuppressionEffect::NoiseSuppressionEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+NoiseSuppressionEffect::~NoiseSuppressionEffect() {}
+
+void NoiseSuppressionEffect::propertiesFromHal(
+        const t_ns_settings& halProperties,
+        INoiseSuppressionEffect::AllProperties* properties) {
+    properties->level = Level(halProperties.level);
+    properties->type = Type(halProperties.type);
+}
+
+void NoiseSuppressionEffect::propertiesToHal(
+        const INoiseSuppressionEffect::AllProperties& properties,
+        t_ns_settings* halProperties) {
+    halProperties->level = static_cast<uint32_t>(properties.level);
+    halProperties->type = static_cast<uint32_t>(properties.type);
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> NoiseSuppressionEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> NoiseSuppressionEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> NoiseSuppressionEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> NoiseSuppressionEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> NoiseSuppressionEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> NoiseSuppressionEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> NoiseSuppressionEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> NoiseSuppressionEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> NoiseSuppressionEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> NoiseSuppressionEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> NoiseSuppressionEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> NoiseSuppressionEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> NoiseSuppressionEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> NoiseSuppressionEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> NoiseSuppressionEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> NoiseSuppressionEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> NoiseSuppressionEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> NoiseSuppressionEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> NoiseSuppressionEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
+Return<Result> NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level)  {
+    return mEffect->setParam(NS_PARAM_LEVEL, static_cast<int32_t>(level));
+}
+
+Return<void> NoiseSuppressionEffect::getSuppressionLevel(getSuppressionLevel_cb _hidl_cb)  {
+    int32_t halLevel = 0;
+    Result retval = mEffect->getParam(NS_PARAM_LEVEL, halLevel);
+    _hidl_cb(retval, Level(halLevel));
+    return Void();
+}
+
+Return<Result> NoiseSuppressionEffect::setSuppressionType(INoiseSuppressionEffect::Type type)  {
+    return mEffect->setParam(NS_PARAM_TYPE, static_cast<int32_t>(type));
+}
+
+Return<void> NoiseSuppressionEffect::getSuppressionType(getSuppressionType_cb _hidl_cb)  {
+    int32_t halType = 0;
+    Result retval = mEffect->getParam(NS_PARAM_TYPE, halType);
+    _hidl_cb(retval, Type(halType));
+    return Void();
+}
+
+Return<Result> NoiseSuppressionEffect::setAllProperties(
+        const INoiseSuppressionEffect::AllProperties& properties)  {
+    t_ns_settings halProperties;
+    propertiesToHal(properties, &halProperties);
+    return mEffect->setParam(NS_PARAM_PROPERTIES, halProperties);
+}
+
+Return<void> NoiseSuppressionEffect::getAllProperties(getAllProperties_cb _hidl_cb)  {
+    t_ns_settings halProperties;
+    Result retval = mEffect->getParam(NS_PARAM_PROPERTIES, halProperties);
+    AllProperties properties;
+    propertiesFromHal(halProperties, &properties);
+    _hidl_cb(retval, properties);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.h b/audio/effect/2.0/default/NoiseSuppressionEffect.h
new file mode 100644
index 0000000..5491201
--- /dev/null
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
+
+#include <system/audio_effects/effect_ns.h>
+
+#include <android/hardware/audio/effect/2.0/INoiseSuppressionEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct NoiseSuppressionEffect : public INoiseSuppressionEffect {
+    explicit NoiseSuppressionEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
+    Return<Result> setSuppressionLevel(INoiseSuppressionEffect::Level level)  override;
+    Return<void> getSuppressionLevel(getSuppressionLevel_cb _hidl_cb)  override;
+    Return<Result> setSuppressionType(INoiseSuppressionEffect::Type type)  override;
+    Return<void> getSuppressionType(getSuppressionType_cb _hidl_cb)  override;
+    Return<Result> setAllProperties(
+            const INoiseSuppressionEffect::AllProperties& properties)  override;
+    Return<void> getAllProperties(getAllProperties_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~NoiseSuppressionEffect();
+
+    void propertiesFromHal(
+            const t_ns_settings& halProperties,
+            INoiseSuppressionEffect::AllProperties* properties);
+    void propertiesToHal(
+            const INoiseSuppressionEffect::AllProperties& properties,
+            t_ns_settings* halProperties);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_NOISESUPPRESSIONEFFECT_H
diff --git a/audio/effect/2.0/default/PresetReverbEffect.cpp b/audio/effect/2.0/default/PresetReverbEffect.cpp
new file mode 100644
index 0000000..5f17791
--- /dev/null
+++ b/audio/effect/2.0/default/PresetReverbEffect.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "PresetReverb_HAL"
+#include <system/audio_effects/effect_presetreverb.h>
+#include <android/log.h>
+
+#include "PresetReverbEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+PresetReverbEffect::PresetReverbEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+PresetReverbEffect::~PresetReverbEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> PresetReverbEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> PresetReverbEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> PresetReverbEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> PresetReverbEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> PresetReverbEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> PresetReverbEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> PresetReverbEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> PresetReverbEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> PresetReverbEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> PresetReverbEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> PresetReverbEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> PresetReverbEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> PresetReverbEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> PresetReverbEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> PresetReverbEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> PresetReverbEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> PresetReverbEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> PresetReverbEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> PresetReverbEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> PresetReverbEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
+Return<Result> PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset)  {
+    return mEffect->setParam(REVERB_PARAM_PRESET, static_cast<t_reverb_presets>(preset));
+}
+
+Return<void> PresetReverbEffect::getPreset(getPreset_cb _hidl_cb)  {
+    t_reverb_presets halPreset = REVERB_PRESET_NONE;
+    Result retval = mEffect->getParam(REVERB_PARAM_PRESET, halPreset);
+    _hidl_cb(retval, Preset(halPreset));
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/PresetReverbEffect.h b/audio/effect/2.0/default/PresetReverbEffect.h
new file mode 100644
index 0000000..4eb074a
--- /dev/null
+++ b/audio/effect/2.0/default/PresetReverbEffect.h
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_PRESETREVERBEFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_PRESETREVERBEFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IPresetReverbEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::IPresetReverbEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct PresetReverbEffect : public IPresetReverbEffect {
+    explicit PresetReverbEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
+    Return<Result> setPreset(IPresetReverbEffect::Preset preset)  override;
+    Return<void> getPreset(getPreset_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~PresetReverbEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_PRESETREVERBEFFECT_H
diff --git a/audio/effect/2.0/default/VirtualizerEffect.cpp b/audio/effect/2.0/default/VirtualizerEffect.cpp
new file mode 100644
index 0000000..c1fe52f
--- /dev/null
+++ b/audio/effect/2.0/default/VirtualizerEffect.cpp
@@ -0,0 +1,248 @@
+/*
+ * 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.
+ */
+
+#include <memory.h>
+
+#define LOG_TAG "Virtualizer_HAL"
+#include <system/audio_effects/effect_virtualizer.h>
+#include <android/log.h>
+
+#include "VirtualizerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+VirtualizerEffect::VirtualizerEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)) {
+}
+
+VirtualizerEffect::~VirtualizerEffect() {}
+
+void VirtualizerEffect::speakerAnglesFromHal(
+        const int32_t* halAngles, uint32_t channelCount, hidl_vec<SpeakerAngle>& speakerAngles) {
+    speakerAngles.resize(channelCount);
+    for (uint32_t i = 0; i < channelCount; ++i) {
+        speakerAngles[i].mask = AudioChannelMask(*halAngles++);
+        speakerAngles[i].azimuth = *halAngles++;
+        speakerAngles[i].elevation = *halAngles++;
+    }
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> VirtualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> VirtualizerEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VirtualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> VirtualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> VirtualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> VirtualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> VirtualizerEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> VirtualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> VirtualizerEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VirtualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> VirtualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> VirtualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> VirtualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> VirtualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> VirtualizerEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> VirtualizerEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> VirtualizerEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> VirtualizerEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> VirtualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
+Return<bool> VirtualizerEffect::isStrengthSupported()  {
+    bool halSupported = false;
+    mEffect->getParam(VIRTUALIZER_PARAM_STRENGTH_SUPPORTED, halSupported);
+    return halSupported;
+}
+
+Return<Result> VirtualizerEffect::setStrength(uint16_t strength)  {
+    return mEffect->setParam(VIRTUALIZER_PARAM_STRENGTH, strength);
+}
+
+Return<void> VirtualizerEffect::getStrength(getStrength_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(VIRTUALIZER_PARAM_STRENGTH, _hidl_cb);
+}
+
+Return<void> VirtualizerEffect::getVirtualSpeakerAngles(
+        AudioChannelMask mask, AudioDevice device, getVirtualSpeakerAngles_cb _hidl_cb)  {
+    uint32_t channelCount = audio_channel_count_from_out_mask(
+            static_cast<audio_channel_mask_t>(mask));
+    size_t halSpeakerAnglesSize = sizeof(int32_t) * 3 * channelCount;
+    uint32_t halParam[3] = {
+        VIRTUALIZER_PARAM_VIRTUAL_SPEAKER_ANGLES,
+        static_cast<audio_channel_mask_t>(mask),
+        static_cast<audio_devices_t>(device)
+    };
+    hidl_vec<SpeakerAngle> speakerAngles;
+    Result retval = mEffect->getParameterImpl(
+            sizeof(halParam), halParam,
+            halSpeakerAnglesSize,
+            [&] (uint32_t valueSize, const void* valueData) {
+                if (valueSize > halSpeakerAnglesSize) {
+                    valueSize = halSpeakerAnglesSize;
+                } else if (valueSize < halSpeakerAnglesSize) {
+                    channelCount = valueSize / (sizeof(int32_t) * 3);
+                }
+                speakerAnglesFromHal(
+                        reinterpret_cast<const int32_t*>(valueData), channelCount, speakerAngles);
+            });
+    _hidl_cb(retval, speakerAngles);
+    return Void();
+}
+
+Return<Result> VirtualizerEffect::forceVirtualizationMode(AudioDevice device)  {
+    return mEffect->setParam(
+            VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, static_cast<audio_devices_t>(device));
+}
+
+Return<void> VirtualizerEffect::getVirtualizationMode(getVirtualizationMode_cb _hidl_cb)  {
+    uint32_t halMode = 0;
+    Result retval = mEffect->getParam(VIRTUALIZER_PARAM_FORCE_VIRTUALIZATION_MODE, halMode);
+    _hidl_cb(retval, AudioDevice(halMode));
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/VirtualizerEffect.h b/audio/effect/2.0/default/VirtualizerEffect.h
new file mode 100644
index 0000000..536775f
--- /dev/null
+++ b/audio/effect/2.0/default/VirtualizerEffect.h
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VIRTUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VIRTUALIZEREFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IVirtualizerEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioChannelMask;
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::IVirtualizerEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct VirtualizerEffect : public IVirtualizerEffect {
+    explicit VirtualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
+    Return<bool> isStrengthSupported()  override;
+    Return<Result> setStrength(uint16_t strength)  override;
+    Return<void> getStrength(getStrength_cb _hidl_cb)  override;
+    Return<void> getVirtualSpeakerAngles(
+            AudioChannelMask mask,
+            AudioDevice device,
+            getVirtualSpeakerAngles_cb _hidl_cb)  override;
+    Return<Result> forceVirtualizationMode(AudioDevice device)  override;
+    Return<void> getVirtualizationMode(getVirtualizationMode_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+
+    virtual ~VirtualizerEffect();
+
+    void speakerAnglesFromHal(
+            const int32_t* halAngles, uint32_t channelCount, hidl_vec<SpeakerAngle>& speakerAngles);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VIRTUALIZEREFFECT_H
diff --git a/audio/effect/2.0/default/VisualizerEffect.cpp b/audio/effect/2.0/default/VisualizerEffect.cpp
new file mode 100644
index 0000000..2cd3240
--- /dev/null
+++ b/audio/effect/2.0/default/VisualizerEffect.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Visualizer_HAL"
+#include <system/audio_effects/effect_visualizer.h>
+#include <android/log.h>
+
+#include "VisualizerEffect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+VisualizerEffect::VisualizerEffect(effect_handle_t handle)
+        : mEffect(new Effect(handle)), mCaptureSize(0), mMeasurementMode(MeasurementMode::NONE) {
+}
+
+VisualizerEffect::~VisualizerEffect() {}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+Return<Result> VisualizerEffect::init() {
+    return mEffect->init();
+}
+
+Return<Result> VisualizerEffect::setConfig(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VisualizerEffect::reset() {
+    return mEffect->reset();
+}
+
+Return<Result> VisualizerEffect::enable() {
+    return mEffect->enable();
+}
+
+Return<Result> VisualizerEffect::disable() {
+    return mEffect->disable();
+}
+
+Return<Result> VisualizerEffect::setDevice(AudioDevice device) {
+    return mEffect->setDevice(device);
+}
+
+Return<void> VisualizerEffect::setAndGetVolume(
+        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
+    return mEffect->setAndGetVolume(volumes, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::volumeChangeNotification(
+        const hidl_vec<uint32_t>& volumes) {
+    return mEffect->volumeChangeNotification(volumes);
+}
+
+Return<Result> VisualizerEffect::setAudioMode(AudioMode mode) {
+    return mEffect->setAudioMode(mode);
+}
+
+Return<Result> VisualizerEffect::setConfigReverse(
+        const EffectConfig& config,
+        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
+    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
+}
+
+Return<Result> VisualizerEffect::setInputDevice(AudioDevice device) {
+    return mEffect->setInputDevice(device);
+}
+
+Return<void> VisualizerEffect::getConfig(getConfig_cb _hidl_cb) {
+    return mEffect->getConfig(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
+    return mEffect->getConfigReverse(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::getSupportedAuxChannelsConfigs(
+        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
+    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
+    return mEffect->getAuxChannelsConfig(_hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setAuxChannelsConfig(
+        const EffectAuxChannelsConfig& config) {
+    return mEffect->setAuxChannelsConfig(config);
+}
+
+Return<Result> VisualizerEffect::setAudioSource(AudioSource source) {
+    return mEffect->setAudioSource(source);
+}
+
+Return<Result> VisualizerEffect::offload(const EffectOffloadParameter& param) {
+    return mEffect->offload(param);
+}
+
+Return<void> VisualizerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
+    return mEffect->getDescriptor(_hidl_cb);
+}
+
+Return<void> VisualizerEffect::prepareForProcessing(
+        prepareForProcessing_cb _hidl_cb) {
+    return mEffect->prepareForProcessing(_hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setProcessBuffers(
+        const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+    return mEffect->setProcessBuffers(inBuffer, outBuffer);
+}
+
+Return<void> VisualizerEffect::command(
+        uint32_t commandId,
+        const hidl_vec<uint8_t>& data,
+        uint32_t resultMaxSize,
+        command_cb _hidl_cb) {
+    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setParameter(
+        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
+    return mEffect->setParameter(parameter, value);
+}
+
+Return<void> VisualizerEffect::getParameter(
+        const hidl_vec<uint8_t>& parameter,
+        uint32_t valueMaxSize,
+        getParameter_cb _hidl_cb) {
+    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getSupportedConfigsForFeature(
+        uint32_t featureId,
+        uint32_t maxConfigs,
+        uint32_t configSize,
+        getSupportedConfigsForFeature_cb _hidl_cb) {
+    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
+}
+
+Return<void> VisualizerEffect::getCurrentConfigForFeature(
+        uint32_t featureId,
+        uint32_t configSize,
+        getCurrentConfigForFeature_cb _hidl_cb) {
+    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setCurrentConfigForFeature(
+        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
+    return mEffect->setCurrentConfigForFeature(featureId, configData);
+}
+
+Return<Result> VisualizerEffect::close() {
+    return mEffect->close();
+}
+
+// Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
+Return<Result> VisualizerEffect::setCaptureSize(uint16_t captureSize)  {
+    Result retval = mEffect->setParam(VISUALIZER_PARAM_CAPTURE_SIZE, captureSize);
+    if (retval == Result::OK) {
+        mCaptureSize = captureSize;
+    }
+    return retval;
+}
+
+Return<void> VisualizerEffect::getCaptureSize(getCaptureSize_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(VISUALIZER_PARAM_CAPTURE_SIZE, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setScalingMode(IVisualizerEffect::ScalingMode scalingMode)  {
+    return mEffect->setParam(VISUALIZER_PARAM_SCALING_MODE, static_cast<int32_t>(scalingMode));
+}
+
+Return<void> VisualizerEffect::getScalingMode(getScalingMode_cb _hidl_cb)  {
+    int32_t halMode;
+    Result retval = mEffect->getParam(VISUALIZER_PARAM_SCALING_MODE, halMode);
+    _hidl_cb(retval, ScalingMode(halMode));
+    return Void();
+}
+
+Return<Result> VisualizerEffect::setLatency(uint32_t latencyMs)  {
+    return mEffect->setParam(VISUALIZER_PARAM_LATENCY, latencyMs);
+}
+
+Return<void> VisualizerEffect::getLatency(getLatency_cb _hidl_cb)  {
+    return mEffect->getIntegerParam(VISUALIZER_PARAM_LATENCY, _hidl_cb);
+}
+
+Return<Result> VisualizerEffect::setMeasurementMode(
+        IVisualizerEffect::MeasurementMode measurementMode)  {
+    Result retval = mEffect->setParam(
+            VISUALIZER_PARAM_MEASUREMENT_MODE, static_cast<int32_t>(measurementMode));
+    if (retval == Result::OK) {
+        mMeasurementMode = measurementMode;
+    }
+    return retval;
+}
+
+Return<void> VisualizerEffect::getMeasurementMode(getMeasurementMode_cb _hidl_cb)  {
+    int32_t halMode;
+    Result retval = mEffect->getParam(VISUALIZER_PARAM_MEASUREMENT_MODE, halMode);
+    _hidl_cb(retval, MeasurementMode(halMode));
+    return Void();
+}
+
+Return<void> VisualizerEffect::capture(capture_cb _hidl_cb)  {
+    if (mCaptureSize == 0) {
+        _hidl_cb(Result::NOT_INITIALIZED, hidl_vec<uint8_t>());
+        return Void();
+    }
+    uint32_t halCaptureSize = mCaptureSize;
+    uint8_t halCapture[mCaptureSize];
+    Result retval = mEffect->sendCommandReturningData(
+            VISUALIZER_CMD_CAPTURE, "VISUALIZER_CAPTURE", &halCaptureSize, halCapture);
+    hidl_vec<uint8_t> capture;
+    if (retval == Result::OK) {
+        capture.setToExternal(&halCapture[0], halCaptureSize);
+    }
+    _hidl_cb(retval, capture);
+    return Void();
+}
+
+Return<void> VisualizerEffect::measure(measure_cb _hidl_cb)  {
+    if (mMeasurementMode == MeasurementMode::NONE) {
+        _hidl_cb(Result::NOT_INITIALIZED, Measurement());
+        return Void();
+    }
+    int32_t halMeasurement[MEASUREMENT_COUNT];
+    uint32_t halMeasurementSize = sizeof(halMeasurement);
+    Result retval = mEffect->sendCommandReturningData(
+            VISUALIZER_CMD_MEASURE, "VISUALIZER_MEASURE", &halMeasurementSize, halMeasurement);
+    Measurement measurement = { .mode = MeasurementMode::PEAK_RMS };
+    measurement.value.peakAndRms.peakMb = 0;
+    measurement.value.peakAndRms.rmsMb = 0;
+    if (retval == Result::OK) {
+        measurement.value.peakAndRms.peakMb = halMeasurement[MEASUREMENT_IDX_PEAK];
+        measurement.value.peakAndRms.rmsMb = halMeasurement[MEASUREMENT_IDX_RMS];
+    }
+    _hidl_cb(retval, measurement);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
diff --git a/audio/effect/2.0/default/VisualizerEffect.h b/audio/effect/2.0/default/VisualizerEffect.h
new file mode 100644
index 0000000..fd40ca8
--- /dev/null
+++ b/audio/effect/2.0/default/VisualizerEffect.h
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VISUALIZEREFFECT_H
+#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VISUALIZEREFFECT_H
+
+#include <android/hardware/audio/effect/2.0/IVisualizerEffect.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include "Effect.h"
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::audio::common::V2_0::AudioMode;
+using ::android::hardware::audio::common::V2_0::AudioSource;
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hardware::audio::effect::V2_0::EffectAuxChannelsConfig;
+using ::android::hardware::audio::effect::V2_0::EffectConfig;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::EffectOffloadParameter;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectBufferProviderCallback;
+using ::android::hardware::audio::effect::V2_0::IVisualizerEffect;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct VisualizerEffect : public IVisualizerEffect {
+    explicit VisualizerEffect(effect_handle_t handle);
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
+    Return<Result> init()  override;
+    Return<Result> setConfig(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> reset()  override;
+    Return<Result> enable()  override;
+    Return<Result> disable()  override;
+    Return<Result> setDevice(AudioDevice device)  override;
+    Return<void> setAndGetVolume(
+            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
+    Return<Result> volumeChangeNotification(const hidl_vec<uint32_t>& volumes)  override;
+    Return<Result> setAudioMode(AudioMode mode)  override;
+    Return<Result> setConfigReverse(
+            const EffectConfig& config,
+            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
+            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
+    Return<Result> setInputDevice(AudioDevice device)  override;
+    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
+    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
+    Return<void> getSupportedAuxChannelsConfigs(
+            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
+    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
+    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
+    Return<Result> setAudioSource(AudioSource source)  override;
+    Return<Result> offload(const EffectOffloadParameter& param)  override;
+    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
+    Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb)  override;
+    Return<Result> setProcessBuffers(
+            const AudioBuffer& inBuffer, const AudioBuffer& outBuffer)  override;
+    Return<void> command(
+            uint32_t commandId,
+            const hidl_vec<uint8_t>& data,
+            uint32_t resultMaxSize,
+            command_cb _hidl_cb)  override;
+    Return<Result> setParameter(
+            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
+    Return<void> getParameter(
+            const hidl_vec<uint8_t>& parameter,
+            uint32_t valueMaxSize,
+            getParameter_cb _hidl_cb)  override;
+    Return<void> getSupportedConfigsForFeature(
+            uint32_t featureId,
+            uint32_t maxConfigs,
+            uint32_t configSize,
+            getSupportedConfigsForFeature_cb _hidl_cb)  override;
+    Return<void> getCurrentConfigForFeature(
+            uint32_t featureId,
+            uint32_t configSize,
+            getCurrentConfigForFeature_cb _hidl_cb)  override;
+    Return<Result> setCurrentConfigForFeature(
+            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;
+    Return<Result> close()  override;
+
+    // Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
+    Return<Result> setCaptureSize(uint16_t captureSize)  override;
+    Return<void> getCaptureSize(getCaptureSize_cb _hidl_cb)  override;
+    Return<Result> setScalingMode(IVisualizerEffect::ScalingMode scalingMode)  override;
+    Return<void> getScalingMode(getScalingMode_cb _hidl_cb)  override;
+    Return<Result> setLatency(uint32_t latencyMs)  override;
+    Return<void> getLatency(getLatency_cb _hidl_cb)  override;
+    Return<Result> setMeasurementMode(IVisualizerEffect::MeasurementMode measurementMode)  override;
+    Return<void> getMeasurementMode(getMeasurementMode_cb _hidl_cb)  override;
+    Return<void> capture(capture_cb _hidl_cb)  override;
+    Return<void> measure(measure_cb _hidl_cb)  override;
+
+  private:
+    sp<Effect> mEffect;
+    uint16_t mCaptureSize;
+    MeasurementMode mMeasurementMode;
+
+    virtual ~VisualizerEffect();
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace effect
+}  // namespace audio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_VISUALIZEREFFECT_H
diff --git a/audio/effect/2.0/types.hal b/audio/effect/2.0/types.hal
new file mode 100644
index 0000000..0cac59a
--- /dev/null
+++ b/audio/effect/2.0/types.hal
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ */
+
+package android.hardware.audio.effect@2.0;
+
+import android.hardware.audio.common@2.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
+    ALL = BUFFER | SMP_RATE | CHANNELS | FORMAT | ACC_MODE
+};
+
+/*
+ * 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;
+    AudioChannelMask channels;
+    AudioFormat format;
+    EffectBufferAccess accessMode;
+    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 {
+    AudioChannelMask mainChannels;  // channel mask for main channels
+    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_PROCESS_ALL = REQUEST_PROCESS | REQUEST_PROCESS_REVERSE
+};
diff --git a/audio/effect/2.0/vts/Android.mk b/audio/effect/2.0/vts/Android.mk
new file mode 100644
index 0000000..abdd5bf
--- /dev/null
+++ b/audio/effect/2.0/vts/Android.mk
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..b82d44a
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/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_test {
+    name: "audio_effect_hidl_hal_test",
+    gtest: true,
+    srcs: ["audio_effect_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.audio.effect@2.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/audio/effect/2.0/vts/functional/Android.mk b/audio/effect/2.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
new file mode 100644
index 0000000..9b7d0cf
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/audio_effect_hidl_hal_test.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioEffectHidlHalTest"
+#include <android-base/logging.h>
+#include <cutils/native_handle.h>
+
+#include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
+#include <android/hardware/audio/effect/2.0/types.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::audio::effect::V2_0::EffectDescriptor;
+using ::android::hardware::audio::effect::V2_0::IEffect;
+using ::android::hardware::audio::effect::V2_0::IEffectsFactory;
+using ::android::hardware::audio::effect::V2_0::Result;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+
+// The main test class for Audio Effect HIDL HAL.
+class AudioEffectHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    // currently test passthrough mode only
+    effectsFactory = IEffectsFactory::getService("audio_effects_factory", true);
+    ASSERT_NE(effectsFactory, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IEffectsFactory> effectsFactory;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class AudioEffectHidlEnvironment : public ::testing::Environment {
+ public:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ private:
+};
+
+TEST_F(AudioEffectHidlTest, EnumerateEffects) {
+  Result retval = Result::NOT_INITIALIZED;
+  size_t effectCount = 0;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        retval = r;
+        effectCount = result.size();
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(retval, Result::OK);
+  EXPECT_GT(effectCount, 0u);
+}
+
+TEST_F(AudioEffectHidlTest, CreateEffect) {
+  bool gotEffect = false;
+  Uuid effectUuid;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK && result.size() > 0) {
+          gotEffect = true;
+          effectUuid = result[0].uuid;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(gotEffect);
+  Result retval = Result::NOT_INITIALIZED;
+  sp<IEffect> effect;
+  ret = effectsFactory->createEffect(
+      effectUuid, 1 /* session */, 1 /* ioHandle */,
+      [&](Result r, const sp<IEffect>& result, uint64_t /*effectId*/) {
+        retval = r;
+        if (r == Result::OK) {
+          effect = result;
+        }
+      });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(retval, Result::OK);
+  EXPECT_NE(effect, nullptr);
+}
+
+TEST_F(AudioEffectHidlTest, GetDescriptor) {
+  hidl_vec<EffectDescriptor> allDescriptors;
+  Return<void> ret = effectsFactory->getAllDescriptors(
+      [&](Result r, const hidl_vec<EffectDescriptor>& result) {
+        if (r == Result::OK) {
+          allDescriptors = result;
+        }
+      });
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_GT(allDescriptors.size(), 0u);
+  for (size_t i = 0; i < allDescriptors.size(); ++i) {
+    ret = effectsFactory->getDescriptor(
+        allDescriptors[i].uuid, [&](Result r, const EffectDescriptor& result) {
+          EXPECT_EQ(r, Result::OK);
+          EXPECT_EQ(result, allDescriptors[i]);
+        });
+  }
+  EXPECT_TRUE(ret.isOk());
+}
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(new AudioEffectHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/audio/effect/2.0/vts/functional/vts/Android.mk b/audio/effect/2.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/Android.mk
new file mode 100644
index 0000000..fe5ea0f
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalAudioEffectHidlTargetBasicTest
+VTS_CONFIG_SRC_DIR := testcases/hal/audio/effect/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/AndroidTest.xml b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..f0af67a
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Audio Effect HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalAudioEffectHidlTargetBasicTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/audio_effect_hidl_hal_test/audio_effect_hidl_hal_test,
+            _64bit::DATA/nativetest64/audio_effect_hidl_hal_test/audio_effect_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/Android.mk b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..430600d
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalAudioEffectHidlTargetBasicProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/audio/effect/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/AndroidTest.xml b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..7febf26
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/vts/testcases/hal/audio/effect/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Audio Effect HIDL HAL's basic target-side, profiling test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalAudioEffectHidlTargetBasicProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/audio_effect_hidl_hal_test/audio_effect_hidl_hal_test,
+            _64bit::DATA/nativetest64/audio_effect_hidl_hal_test/audio_effect_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/audio/effect/Android.mk b/audio/effect/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/audio/effect/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/biometrics/Android.bp b/biometrics/Android.bp
new file mode 100644
index 0000000..eea4604
--- /dev/null
+++ b/biometrics/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "fingerprint/2.1",
+]
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
new file mode 100644
index 0000000..02b7328
--- /dev/null
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -0,0 +1,64 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1",
+    srcs: [
+        "types.hal",
+        "IBiometricsFingerprint.hal",
+        "IBiometricsFingerprintClientCallback.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/types.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintAll.cpp",
+        "android/hardware/biometrics/fingerprint/2.1/BiometricsFingerprintClientCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.biometrics.fingerprint@2.1_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.biometrics.fingerprint@2.1",
+    srcs: [
+        "types.hal",
+        "IBiometricsFingerprint.hal",
+        "IBiometricsFingerprintClientCallback.hal",
+    ],
+    out: [
+        "android/hardware/biometrics/fingerprint/2.1/types.h",
+        "android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h",
+        "android/hardware/biometrics/fingerprint/2.1/IHwBiometricsFingerprint.h",
+        "android/hardware/biometrics/fingerprint/2.1/BnHwBiometricsFingerprint.h",
+        "android/hardware/biometrics/fingerprint/2.1/BpHwBiometricsFingerprint.h",
+        "android/hardware/biometrics/fingerprint/2.1/BsBiometricsFingerprint.h",
+        "android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h",
+        "android/hardware/biometrics/fingerprint/2.1/IHwBiometricsFingerprintClientCallback.h",
+        "android/hardware/biometrics/fingerprint/2.1/BnHwBiometricsFingerprintClientCallback.h",
+        "android/hardware/biometrics/fingerprint/2.1/BpHwBiometricsFingerprintClientCallback.h",
+        "android/hardware/biometrics/fingerprint/2.1/BsBiometricsFingerprintClientCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.biometrics.fingerprint@2.1",
+    generated_sources: ["android.hardware.biometrics.fingerprint@2.1_genc++"],
+    generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
+    export_generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/biometrics/fingerprint/2.1/Android.mk b/biometrics/fingerprint/2.1/Android.mk
new file mode 100644
index 0000000..22da268
--- /dev/null
+++ b/biometrics/fingerprint/2.1/Android.mk
@@ -0,0 +1,468 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.1-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (FingerprintAcquired)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAcquired.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAcquired
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintAcquiredInfo)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAcquiredInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAcquiredInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintAuthenticated)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAuthenticated.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAuthenticated
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintEnroll)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintEnroll.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintEnroll
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintError)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintError.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintError
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintFingerId)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintFingerId.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintFingerId
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintIterator)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintIterator.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintIterator
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintMsgType)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintMsgType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintMsgType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (RequestStatus)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/RequestStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.RequestStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBiometricsFingerprint.hal
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBiometricsFingerprint.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
+
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprint.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBiometricsFingerprintClientCallback.hal
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprintClientCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
+
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.1-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (FingerprintAcquired)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAcquired.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAcquired
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintAcquiredInfo)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAcquiredInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAcquiredInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintAuthenticated)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintAuthenticated.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintAuthenticated
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintEnroll)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintEnroll.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintEnroll
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintError)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintError.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintError
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintFingerId)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintFingerId.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintFingerId
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintIterator)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintIterator.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintIterator
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FingerprintMsgType)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/FingerprintMsgType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.FingerprintMsgType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (RequestStatus)
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/RequestStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::types.RequestStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBiometricsFingerprint.hal
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBiometricsFingerprint.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
+
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprint.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBiometricsFingerprintClientCallback.hal
+#
+GEN := $(intermediates)/android/hardware/biometrics/fingerprint/V2_1/IBiometricsFingerprintClientCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
+
+$(GEN): $(LOCAL_PATH)/IBiometricsFingerprintClientCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/biometrics/fingerprint/2.1/IBiometricsFingerprint.hal b/biometrics/fingerprint/2.1/IBiometricsFingerprint.hal
new file mode 100644
index 0000000..0b92848
--- /dev/null
+++ b/biometrics/fingerprint/2.1/IBiometricsFingerprint.hal
@@ -0,0 +1,164 @@
+/*
+ * 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.biometrics.fingerprint@2.1;
+
+import IBiometricsFingerprintClientCallback;
+
+interface IBiometricsFingerprint {
+  /*
+   * Set notification callback:
+   * Registers a user function that must receive notifications from the HAL
+   * This call must block if the HAL state machine is in busy state until HAL
+   * leaves the busy state.
+   *
+   * @return deviceId is a unique handle for this fingerprint device
+   */
+  @callflow(next={"setActiveGroup"})
+  @entry
+  setNotify(IBiometricsFingerprintClientCallback clientCallback)
+      generates (uint64_t deviceId);
+
+  /*
+   * Fingerprint pre-enroll enroll request:
+   * Generates a unique token to upper layers to indicate the start of
+   * an enrollment transaction. pre-enroll and post-enroll specify
+   * a pin/password cleared time window where enrollment is allowed.
+   * Pre-enroll only generates a challenge, a full hardwareAuthToken is
+   * generated by trustzone after verifying a pin/password/swipe. This is to
+   * ensure adding a new fingerprint template was preceded by some kind of
+   * credential confirmation (e.g. device password).
+   *
+   * @return 0 if function failed, a uint64_t of challenge otherwise.
+   */
+  @callflow(next={"enroll", "postEnroll"})
+  preEnroll() generates (uint64_t authChallenge);
+
+  /*
+   * Fingerprint enroll request:
+   * Switches the HAL state machine to collect and store a new fingerprint
+   * template. Switches back as soon as enroll is complete, signalled by
+   * (fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENROLLING &&
+   *  fingerprintMsg.data.enroll.samplesRemaining == 0)
+   * or after timeoutSec seconds.
+   * The fingerprint template must be assigned to the group gid.
+   *
+   * @param hat a valid Hardware Authentication Token (HAT), generated
+   * as a result of a preEnroll() call.
+   * @param gid a framework defined fingerprint set (group) id.
+   * @param timeoutSec a timeout in seconds.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   *
+   * A notify() function may be called with a more detailed error structure.
+   */
+  @callflow(next={"cancel", "enroll", "postEnroll", "remove"})
+  enroll(uint8_t[69] hat, uint32_t gid, uint32_t timeoutSec)
+      generates (RequestStatus debugErrno);
+
+  /*
+   * Finishes the enroll operation and invalidates the preEnroll() generated
+   * challenge. This must be called at the end of a multi-finger enrollment
+   * session to indicate that no more fingers may be added.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"authenticate", "setActiveGroup", "enumerate", "remove"})
+  postEnroll() generates (RequestStatus debugErrno);
+
+  /*
+   * getAuthenticatorId:
+   * Returns a token associated with the current fingerprint set. This value
+   * must change whenever a new fingerprint is enrolled, thus creating a new
+   * fingerprint set.
+   *
+   * @return getAuthenticatorIdRet current authenticator id, 0 if function
+   * failed.
+   */
+  @callflow(next={"authenticate"})
+  getAuthenticatorId() generates (uint64_t AuthenticatorId);
+
+  /*
+   * Cancel pending enroll or authenticate, sending FINGERPRINT_ERROR_CANCELED
+   * to all running clients. Switches the HAL state machine back to the idle
+   * state. Unlike enrollDone() doesn't invalidate the preEnroll() challenge.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"authenticate", "enroll", "enumerate", "remove",
+    "setActiveGroup"})
+  cancel() generates (RequestStatus debugErrno);
+
+  /*
+   * Enumerate all the fingerprint templates found in the directory set by
+   * setActiveGroup():
+   * For each template found a notify() must be called with:
+   * fingerprintMsg.type == FINGERPRINT_TEMPLATE_ENUMERATED
+   * fingerprintMsg.data.enumerated.finger indicating a template id
+   * fingerprintMsg.data.enumerated.remainingTemplates indicating how many more
+   * enumeration messages to expect.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"remove", "enroll", "authenticate", "setActiveGroup"})
+  enumerate() generates (RequestStatus debugErrno);
+
+  /*
+   * Fingerprint remove request:
+   * Deletes fingerprint template(s).
+   * Works only within the path set by setActiveGroup().
+   * For each template found a notify() must be called with:
+   * fingerprintMsg.type == FINGERPRINT_TEMPLATE_REMOVED
+   * fingerprintMsg.data.removed.finger indicating the template id deleted
+   * fingerprintMsg.data.removed.remainingTemplates indicating how many more
+   * templates must be deleted by this operation.
+   *
+   * @param gid group id must match the last group set by setActiveGroup().
+   * @param fid template id to delete or 0 to delete all templates within the
+   * current group.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"enumerate", "authenticate", "cancel", "getAuthenticatorId",
+    "setActiveGroup"})
+  remove(uint32_t gid, uint32_t fid) generates (RequestStatus debugErrno);
+
+  /*
+   * Restricts the HAL operation to a set of fingerprints belonging to a group
+   * provided. The caller must provide a path to a storage location within the
+   * user's data directory.
+   *
+   * @param gid the fingerprint group (set) id.
+   * @param storePath filesystem path to the template storage directory.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"})
+  setActiveGroup(uint32_t gid, string storePath)
+      generates (RequestStatus debugErrno);
+
+  /*
+   * Authenticates an operation identified by operationId
+   *
+   * @param operationId operation id.
+   * @param gid fingerprint group id.
+   *
+   * @return debugErrno is a value the framework logs in case it is not 0.
+   */
+  @callflow(next={"cancel", "preEnroll", "remove"})
+  authenticate(uint64_t operationId, uint32_t gid)
+      generates (RequestStatus debugErrno);
+};
diff --git a/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal b/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal
new file mode 100644
index 0000000..63435d1
--- /dev/null
+++ b/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.hal
@@ -0,0 +1,75 @@
+/*
+ * 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.biometrics.fingerprint@2.1;
+
+/* This HAL interface communicates asynchronous results from the
+   fingerprint driver in response to user actions on the fingerprint sensor
+*/
+interface IBiometricsFingerprintClientCallback {
+    /**
+     * Sent when one enrollment step is complete.
+     * @param deviceId the instance of this fingerprint device
+     * @param fingerId the fingerprint templetate being enrolled
+     * @param groupId the groupid for the template being enrolled
+     * @param remaining the number of remaining steps before enrolllment is complete
+     */
+    oneway onEnrollResult(uint64_t deviceId, uint32_t fingerId, uint32_t groupId, uint32_t remaining);
+
+    /**
+     * Sent when a fingerprint image is acquired by the sensor
+     * @param deviceId the instance of this fingerprint device
+     * @param acquiredInfo a message about the quality of the acquired image
+     * @param vendorCode a vendor-specific message about the quality of the image. Only
+     *        valid when acquiredInfo == ACQUIRED_VENDOR
+     */
+    oneway onAcquired(uint64_t deviceId, FingerprintAcquiredInfo acquiredInfo, int32_t vendorCode);
+
+    /**
+     * Sent when a fingerprint is authenticated
+     * @param deviceId the instance of this fingerprint device
+     * @param fingerId the fingerprint templetate that was authenticated
+     * @param groupId the groupid for the template that was authenticated
+     */
+    oneway onAuthenticated(uint64_t deviceId, uint32_t fingerId, uint32_t groupId);
+
+    /**
+     * Sent when a fingerprint error occurs
+     * @param deviceId the instance of this fingerprint device
+     * @param error a message about the error that occurred
+     * @param vendorCode a vendor-speicifc error message. Only valid
+     *        when error == ERROR_VENDOR
+     */
+    oneway onError(uint64_t deviceId, FingerprintError error, int32_t vendorCode);
+
+    /**
+     * Sent when one template is removed
+     * @param deviceId the instance of this fingerprint device
+     * @param fingerId the fingerprint templetate being removed
+     * @param groupId the groupid for the template being removed
+     * @param remaining the number of remaining templates that will be removed.
+     */
+    oneway onRemoved(uint64_t deviceId, uint32_t fingerId, uint32_t groupId, uint32_t remaining);
+
+    /**
+     * Sent when one fingerprint template is enumerated
+     * @param deviceId the instance of this fingerprint device
+     * @param fingerId the fingerprint for this templetate
+     * @param groupId the groupid for this template
+     * @param remaining the number of remaining steps before enumeration is complete
+     */
+    oneway onEnumerate(uint64_t deviceId, uint32_t fingerId, uint32_t groupId, uint32_t remaining);
+};
diff --git a/biometrics/fingerprint/2.1/default/Android.mk b/biometrics/fingerprint/2.1/default/Android.mk
new file mode 100644
index 0000000..e5c79fe
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.biometrics.fingerprint@2.1-service
+LOCAL_INIT_RC := android.hardware.biometrics.fingerprint@2.1-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    BiometricsFingerprint.cpp \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    liblog \
+    libhidlbase \
+    libhidltransport \
+    libhardware \
+    libhwbinder \
+    libkeystore_binder \
+    libutils \
+    android.hardware.biometrics.fingerprint@2.1 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
new file mode 100644
index 0000000..516cd00
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.biometrics.fingerprint@2.1-service"
+
+// For communication with Keystore binder interface
+#include <binder/IServiceManager.h>
+#include <keystore/IKeystoreService.h>
+#include <keystore/keystore.h> // for error codes
+#include <hardware/hw_auth_token.h>
+
+#include <hardware/hardware.h>
+#include <hardware/fingerprint.h>
+#include "BiometricsFingerprint.h"
+
+#include <inttypes.h>
+
+namespace android {
+namespace hardware {
+namespace biometrics {
+namespace fingerprint {
+namespace V2_1 {
+namespace implementation {
+
+// Supported fingerprint HAL version
+static const uint16_t kVersion = HARDWARE_MODULE_API_VERSION(2, 1);
+
+using RequestStatus =
+        android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
+
+sp<IBiometricsFingerprintClientCallback>
+    BiometricsFingerprint::mClientCallback = nullptr;
+
+// TODO: This is here because HAL 2.1 doesn't have a way to propagate a
+// unique token for its driver. Subsequent versions should send a unique
+// token for each call to notify(). This is fine as long as there's only
+// one fingerprint device on the platform.
+fingerprint_device_t *BiometricsFingerprint::sDevice = nullptr;
+
+BiometricsFingerprint::BiometricsFingerprint(fingerprint_device_t *device)
+    : mDevice(device) {
+    sDevice = mDevice; // keep track of the most recent instance
+}
+
+BiometricsFingerprint::~BiometricsFingerprint() {
+    ALOG(LOG_VERBOSE, LOG_TAG, "nativeCloseHal()\n");
+    if (mDevice == NULL) {
+        ALOGE("No valid device");
+        return;
+    }
+    int err;
+    if (0 != (err = mDevice->common.close(
+            reinterpret_cast<hw_device_t*>(mDevice)))) {
+        ALOGE("Can't close fingerprint module, error: %d", err);
+        return;
+    }
+    mDevice = NULL;
+}
+
+Return<RequestStatus> BiometricsFingerprint::ErrorFilter(int32_t error) {
+    switch(error) {
+        case 0: return RequestStatus::SYS_OK;
+        case -2: return RequestStatus::SYS_ENOENT;
+        case -4: return RequestStatus::SYS_EINTR;
+        case -5: return RequestStatus::SYS_EIO;
+        case -11: return RequestStatus::SYS_EAGAIN;
+        case -12: return RequestStatus::SYS_ENOMEM;
+        case -13: return RequestStatus::SYS_EACCES;
+        case -14: return RequestStatus::SYS_EFAULT;
+        case -16: return RequestStatus::SYS_EBUSY;
+        case -22: return RequestStatus::SYS_EINVAL;
+        case -28: return RequestStatus::SYS_ENOSPC;
+        case -110: return RequestStatus::SYS_ETIMEDOUT;
+        default:
+            ALOGE("An unknown error returned from fingerprint vendor library");
+            return RequestStatus::SYS_UNKNOWN;
+    }
+}
+
+// Translate from errors returned by traditional HAL (see fingerprint.h) to
+// HIDL-compliant FingerprintError.
+FingerprintError BiometricsFingerprint::VendorErrorFilter(int32_t error,
+            int32_t* vendorCode) {
+    *vendorCode = 0;
+    switch(error) {
+        case FINGERPRINT_ERROR_HW_UNAVAILABLE:
+            return FingerprintError::ERROR_HW_UNAVAILABLE;
+        case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
+            return FingerprintError::ERROR_UNABLE_TO_PROCESS;
+        case FINGERPRINT_ERROR_TIMEOUT:
+            return FingerprintError::ERROR_TIMEOUT;
+        case FINGERPRINT_ERROR_NO_SPACE:
+            return FingerprintError::ERROR_NO_SPACE;
+        case FINGERPRINT_ERROR_CANCELED:
+            return FingerprintError::ERROR_CANCELED;
+        case FINGERPRINT_ERROR_UNABLE_TO_REMOVE:
+            return FingerprintError::ERROR_UNABLE_TO_REMOVE;
+        default:
+            if (error >= FINGERPRINT_ERROR_VENDOR_BASE) {
+                // vendor specific code.
+                *vendorCode = error - FINGERPRINT_ERROR_VENDOR_BASE;
+                return FingerprintError::ERROR_VENDOR;
+            }
+    }
+    ALOGE("Unknown error from fingerprint vendor library");
+    return FingerprintError::ERROR_UNABLE_TO_PROCESS;
+}
+
+// Translate acquired messages returned by traditional HAL (see fingerprint.h)
+// to HIDL-compliant FingerprintAcquiredInfo.
+FingerprintAcquiredInfo BiometricsFingerprint::VendorAcquiredFilter(
+        int32_t info, int32_t* vendorCode) {
+    *vendorCode = 0;
+    switch(info) {
+        case FINGERPRINT_ACQUIRED_GOOD:
+            return FingerprintAcquiredInfo::ACQUIRED_GOOD;
+        case FINGERPRINT_ACQUIRED_PARTIAL:
+            return FingerprintAcquiredInfo::ACQUIRED_PARTIAL;
+        case FINGERPRINT_ACQUIRED_INSUFFICIENT:
+            return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
+        case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
+            return FingerprintAcquiredInfo::ACQUIRED_IMAGER_DIRTY;
+        case FINGERPRINT_ACQUIRED_TOO_SLOW:
+            return FingerprintAcquiredInfo::ACQUIRED_TOO_SLOW;
+        case FINGERPRINT_ACQUIRED_TOO_FAST:
+            return FingerprintAcquiredInfo::ACQUIRED_TOO_FAST;
+        default:
+            if (info >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
+                // vendor specific code.
+                *vendorCode = info - FINGERPRINT_ACQUIRED_VENDOR_BASE;
+                return FingerprintAcquiredInfo::ACQUIRED_VENDOR;
+            }
+    }
+    ALOGE("Unknown acquiredmsg from fingerprint vendor library");
+    return FingerprintAcquiredInfo::ACQUIRED_INSUFFICIENT;
+}
+
+Return<uint64_t> BiometricsFingerprint::setNotify(
+        const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
+    mClientCallback = clientCallback;
+    return reinterpret_cast<uint64_t>(mDevice);
+}
+
+Return<uint64_t> BiometricsFingerprint::preEnroll()  {
+    return mDevice->pre_enroll(mDevice);
+}
+
+Return<RequestStatus> BiometricsFingerprint::enroll(const hidl_array<uint8_t, 69>& hat,
+        uint32_t gid, uint32_t timeoutSec) {
+    const hw_auth_token_t* authToken =
+        reinterpret_cast<const hw_auth_token_t*>(hat.data());
+    return ErrorFilter(mDevice->enroll(mDevice, authToken, gid, timeoutSec));
+}
+
+Return<RequestStatus> BiometricsFingerprint::postEnroll() {
+    return ErrorFilter(mDevice->post_enroll(mDevice));
+}
+
+Return<uint64_t> BiometricsFingerprint::getAuthenticatorId() {
+    return mDevice->get_authenticator_id(mDevice);
+}
+
+Return<RequestStatus> BiometricsFingerprint::cancel() {
+    return ErrorFilter(mDevice->cancel(mDevice));
+}
+
+Return<RequestStatus> BiometricsFingerprint::enumerate()  {
+    return ErrorFilter(mDevice->enumerate(mDevice));
+}
+
+Return<RequestStatus> BiometricsFingerprint::remove(uint32_t gid, uint32_t fid) {
+    return ErrorFilter(mDevice->remove(mDevice, gid, fid));
+}
+
+Return<RequestStatus> BiometricsFingerprint::setActiveGroup(uint32_t gid,
+        const hidl_string& storePath) {
+    if (storePath.size() >= PATH_MAX || storePath.size() <= 0) {
+        ALOGE("Bad path length: %zd", storePath.size());
+    }
+    return ErrorFilter(mDevice->set_active_group(mDevice, gid,
+                                                    storePath.c_str()));
+}
+
+Return<RequestStatus> BiometricsFingerprint::authenticate(uint64_t operationId,
+        uint32_t gid) {
+    return ErrorFilter(mDevice->authenticate(mDevice, operationId, gid));
+}
+
+IBiometricsFingerprint* BiometricsFingerprint::getInstance() {
+    int err;
+    const hw_module_t *hw_mdl = NULL;
+    ALOGE("Opening fingerprint hal library...");
+    if (0 != (err = hw_get_module(FINGERPRINT_HARDWARE_MODULE_ID, &hw_mdl))) {
+        ALOGE("Can't open fingerprint HW Module, error: %d", err);
+        return nullptr;
+    }
+
+    if (hw_mdl == NULL) {
+        ALOGE("No valid fingerprint module");
+        return nullptr;
+    }
+
+    fingerprint_module_t const *module =
+        reinterpret_cast<const fingerprint_module_t*>(hw_mdl);
+    if (module->common.methods->open == NULL) {
+        ALOGE("No valid open method");
+        return nullptr;
+    }
+
+    hw_device_t *device = NULL;
+
+    if (0 != (err = module->common.methods->open(hw_mdl, NULL, &device))) {
+        ALOGE("Can't open fingerprint methods, error: %d", err);
+        return nullptr;
+    }
+
+    if (kVersion != device->version) {
+        ALOGE("Wrong fp version. Expected %d, got %d", kVersion, device->version);
+        return 0; // enforce this on new devices because of HIDL translation layer
+    }
+
+    fingerprint_device_t* fp_device =
+        reinterpret_cast<fingerprint_device_t*>(device);
+
+    if (0 != (err =
+            fp_device->set_notify(fp_device, BiometricsFingerprint::notify))) {
+        ALOGE("Can't register fingerprint module callback, error: %d", err);
+        return nullptr;
+    }
+
+    return new BiometricsFingerprint(fp_device);
+}
+
+void BiometricsFingerprint::notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length) {
+    if (auth_token != nullptr && auth_token_length > 0) {
+        // TODO: cache service?
+        sp<IServiceManager> sm = android::defaultServiceManager();
+        sp<::android::IBinder> binder = sm->getService(String16("android.security.keystore"));
+        sp<IKeystoreService> service = interface_cast<IKeystoreService>(binder);
+        if (service != nullptr) {
+            auto ret = service->addAuthToken(auth_token, auth_token_length);
+            if (!ret.isOk()) {
+                ALOGE("Failure sending auth token to KeyStore: %" PRId32, int32_t(ret));
+            }
+        } else {
+            ALOGE("Unable to communicate with KeyStore");
+        }
+    }
+}
+
+} // namespace implementation
+}  // namespace V2_1
+}  // namespace fingerprint
+}  // namespace biometrics
+}  // namespace hardware
+}  // namespace android
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
new file mode 100644
index 0000000..1f44a1c
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H
+#define ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H
+
+#include <log/log.h>
+#include <android/log.h>
+#include <hardware/hardware.h>
+#include <hardware/fingerprint.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
+
+namespace android {
+namespace hardware {
+namespace biometrics {
+namespace fingerprint {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
+using ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprintClientCallback;
+using ::android::hardware::biometrics::fingerprint::V2_1::RequestStatus;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct BiometricsFingerprint : public IBiometricsFingerprint {
+public:
+    BiometricsFingerprint(fingerprint_device_t *device);
+    ~BiometricsFingerprint();
+
+    // Method to wrap legacy HAL with BiometricsFingerprint class
+    static IBiometricsFingerprint* getInstance();
+
+    // Methods from ::android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint follow.
+    Return<uint64_t> setNotify(const sp<IBiometricsFingerprintClientCallback>& clientCallback) override;
+    Return<uint64_t> preEnroll() override;
+    Return<RequestStatus> enroll(const hidl_array<uint8_t, 69>& hat, uint32_t gid, uint32_t timeoutSec) override;
+    Return<RequestStatus> postEnroll() override;
+    Return<uint64_t> getAuthenticatorId() override;
+    Return<RequestStatus> cancel() override;
+    Return<RequestStatus> enumerate() override;
+    Return<RequestStatus> remove(uint32_t gid, uint32_t fid) override;
+    Return<RequestStatus> setActiveGroup(uint32_t gid, const hidl_string& storePath) override;
+    Return<RequestStatus> authenticate(uint64_t operationId, uint32_t gid) override;
+    static void notify(const fingerprint_msg_t *msg) {
+        if (mClientCallback == nullptr) {
+            ALOGE("Receiving callbacks before the client callback is registered.");
+            return;
+        }
+        const uint64_t devId = reinterpret_cast<uint64_t>(sDevice);
+        switch (msg->type) {
+            case FINGERPRINT_ERROR: {
+                int32_t vendorCode = 0;
+                FingerprintError result =
+                    VendorErrorFilter(msg->data.error, &vendorCode);
+                mClientCallback->onError(devId, result, vendorCode);
+                }
+                break;
+            case FINGERPRINT_ACQUIRED: {
+                int32_t vendorCode = 0;
+                FingerprintAcquiredInfo result =
+                    VendorAcquiredFilter(msg->data.acquired.acquired_info,
+                                         &vendorCode);
+                mClientCallback->onAcquired(devId, result, vendorCode);
+                }
+                break;
+            case FINGERPRINT_TEMPLATE_ENROLLING:
+                mClientCallback->onEnrollResult(devId,
+                    msg->data.enroll.finger.fid,
+                    msg->data.enroll.finger.gid,
+                    msg->data.enroll.samples_remaining);
+                break;
+            case FINGERPRINT_TEMPLATE_REMOVED:
+                mClientCallback->onRemoved(devId,
+                    msg->data.removed.finger.fid,
+                    msg->data.removed.finger.gid,
+                    msg->data.removed.remaining_templates);
+                break;
+            case FINGERPRINT_AUTHENTICATED:
+                if (msg->data.authenticated.finger.fid != 0) {
+                    const uint8_t* hat =
+                            reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
+                    notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
+                }
+                mClientCallback->onAuthenticated(devId,
+                    msg->data.authenticated.finger.fid,
+                    msg->data.authenticated.finger.gid);
+                break;
+            case FINGERPRINT_TEMPLATE_ENUMERATING:
+                mClientCallback->onEnumerate(devId,
+                    msg->data.enumerated.finger.fid,
+                    msg->data.enumerated.finger.gid,
+                    msg->data.enumerated.remaining_templates);
+                break;
+        }
+    }
+private:
+    Return<RequestStatus> ErrorFilter(int32_t error);
+    static void notifyKeystore(const uint8_t *auth_token, const size_t auth_token_length);
+    static FingerprintError VendorErrorFilter(int32_t error,
+            int32_t* vendorCode);
+    static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error,
+            int32_t* vendorCode);
+    static sp<IBiometricsFingerprintClientCallback> mClientCallback;
+    fingerprint_device_t *mDevice;
+    static fingerprint_device_t *sDevice; // TODO: allow multiple drivers
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace fingerprint
+}  // namespace biometrics
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BIOMETRICS_FINGERPRINT_V2_1_BIOMETRICSFINGERPRINT_H
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
new file mode 100644
index 0000000..3de52ad
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
@@ -0,0 +1,7 @@
+service fps_hal /system/bin/hw/android.hardware.biometrics.fingerprint@2.1-service
+    # "class hal" causes a race condition on some devices due to files created
+    # in /data. As a workaround, postpone startup until later in boot once
+    # /data is mounted.
+    class late_start
+    user system
+    group system input
diff --git a/biometrics/fingerprint/2.1/default/service.cpp b/biometrics/fingerprint/2.1/default/service.cpp
new file mode 100644
index 0000000..0563acb
--- /dev/null
+++ b/biometrics/fingerprint/2.1/default/service.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.biometrics.fingerprint@2.1-service"
+
+#include <android/log.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprint.h>
+#include <android/hardware/biometrics/fingerprint/2.1/types.h>
+#include "BiometricsFingerprint.h"
+
+using android::hardware::biometrics::fingerprint::V2_1::IBiometricsFingerprint;
+using android::hardware::biometrics::fingerprint::V2_1::implementation::BiometricsFingerprint;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::sp;
+
+int main() {
+    android::sp<IBiometricsFingerprint> bio = BiometricsFingerprint::getInstance();
+
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+
+    if (bio != nullptr) {
+        bio->registerAsService("fingerprint_hal");
+    } else {
+        ALOGE("Can't create instance of BiometricsFingerprint, nullptr");
+    }
+
+    joinRpcThreadpool();
+
+    return 0; // should never get here
+}
diff --git a/biometrics/fingerprint/2.1/types.hal b/biometrics/fingerprint/2.1/types.hal
new file mode 100644
index 0000000..f462906
--- /dev/null
+++ b/biometrics/fingerprint/2.1/types.hal
@@ -0,0 +1,143 @@
+/*
+ * 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.biometrics.fingerprint@2.1;
+
+/*
+ * Request status indicates whether the request is accepted by the vendor
+ * implementation or not. These values are taken from the errno set,
+ * except for the SYS_UNKNOWN
+ */
+enum RequestStatus : int32_t {
+  SYS_UNKNOWN = 1,
+  SYS_OK = 0,
+  SYS_ENOENT = -2,
+  SYS_EINTR = -4,
+  SYS_EIO = -5,
+  SYS_EAGAIN = -11,
+  SYS_ENOMEM = -12,
+  SYS_EACCES = -13,
+  SYS_EFAULT = -14,
+  SYS_EBUSY = -16,
+  SYS_EINVAL = -22,
+  SYS_ENOSPC = -28,
+  SYS_ETIMEDOUT = -110,
+};
+
+/*
+ * Fingerprint errors are meant to tell the framework to terminate the current
+ * operation and ask for the user to correct the situation. These will almost
+ * always result in messaging and user interaction to correct the problem.
+ *
+ * For example, ERROR_CANCELED should follow any acquisition message that
+ * results in a situation where the current operation can't continue without
+ * user interaction. For example, if the sensor is dirty during enrollment and
+ * no further enrollment progress can be made, send ACQUIRED_IMAGER_DIRTY
+ * followed by ERROR_CANCELED.
+ */
+enum FingerprintError : int32_t {
+  /* The hardware has an error that can't be resolved. */
+  ERROR_HW_UNAVAILABLE = 1,
+  /* Bad data; operation can't continue */
+  ERROR_UNABLE_TO_PROCESS = 2,
+  /* The operation has timed out waiting for user input. */
+  ERROR_TIMEOUT = 3,
+  /* No space available to store a template */
+  ERROR_NO_SPACE = 4,
+  /* The current operation has been canceled */
+  ERROR_CANCELED = 5,
+  /* Unable to remove a template */
+  ERROR_UNABLE_TO_REMOVE = 6,
+  /* The hardware is in lockout due to too many attempts */
+  ERROR_LOCKOUT = 7,
+  /* Vendor-specific error message */
+  ERROR_VENDOR = 8
+};
+
+/*
+ * Fingerprint acquisition info is meant as feedback for the current operation.
+ * Anything but ACQUIRED_GOOD must be shown to the user as feedback on how to
+ * take action on the current operation. For example, ACQUIRED_IMAGER_DIRTY may
+ * be used to tell the user to clean the sensor if it is detected to be dirty.
+ * If this causes the current operation to fail, an additional ERROR_CANCELED
+ * must be sent to stop the operation in progress (e.g. enrollment).
+ * In general, these messages will result in a "Try again" message.
+ */
+enum FingerprintAcquiredInfo : int32_t {
+  ACQUIRED_GOOD = 0,
+  /* sensor needs more data, i.e. longer swipe. */
+  ACQUIRED_PARTIAL = 1,
+  /* image doesn't contain enough detail for recognition*/
+  ACQUIRED_INSUFFICIENT = 2,
+  /* sensor needs to be cleaned */
+  ACQUIRED_IMAGER_DIRTY = 3,
+  /* mostly swipe-type sensors; not enough data collected */
+  ACQUIRED_TOO_SLOW = 4,
+  /* vendor-specific acquisition messages start here */
+  ACQUIRED_TOO_FAST = 5,
+  /* vendor-specific acquisition messages */
+  ACQUIRED_VENDOR = 6
+};
+
+struct FingerprintFingerId {
+  /* Group ID */
+  uint32_t gid;
+  /* Fingerprint template ID */
+  uint32_t fid;
+};
+
+struct FingerprintEnroll {
+  /* Template ID */
+  FingerprintFingerId finger;
+  /* samplesRemaining goes from N (no data collected, but N scans needed)
+   * to 0 (no more data is needed to build a template). */
+  uint32_t samplesRemaining;
+  /* Vendor specific message. Used for user guidance */
+  uint64_t msg;
+};
+
+struct FingerprintIterator {
+  /* Template ID */
+  FingerprintFingerId finger;
+  /* How many templates remain to iterate through */
+  uint32_t remainingTemplates;
+};
+
+typedef FingerprintIterator FingerprintEnumerated;
+typedef FingerprintIterator FingerprintRemoved;
+
+struct FingerprintAcquired {
+  /* information about the image */
+  FingerprintAcquiredInfo acquiredInfo;
+};
+
+struct FingerprintAuthenticated {
+  /* Matched template ID */
+  FingerprintFingerId finger;
+  /* Authentication result from the keymaster */
+  uint8_t[69] hat;
+};
+
+/* Run time type identification for the notify() call payload. */
+enum FingerprintMsgType : int32_t {
+  ERROR = -1,
+  ACQUIRED = 1,
+  TEMPLATE_ENROLLING = 3,
+  TEMPLATE_REMOVED = 4,
+  AUTHENTICATED = 5,
+  TEMPLATE_ENUMERATING = 6,
+};
+
diff --git a/boot/1.0/default/BootControl.cpp b/boot/1.0/default/BootControl.cpp
index 83ee1d2..9a90076 100644
--- a/boot/1.0/default/BootControl.cpp
+++ b/boot/1.0/default/BootControl.cpp
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #define LOG_TAG "android.hardware.boot@1.0-impl"
 
 #include <log/log.h>
diff --git a/boot/1.0/default/BootControl.h b/boot/1.0/default/BootControl.h
index be8a814..3d668dc 100644
--- a/boot/1.0/default/BootControl.h
+++ b/boot/1.0/default/BootControl.h
@@ -1,3 +1,18 @@
+/*
+ * 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.
+ */
 #ifndef ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H
 #define ANDROID_HARDWARE_BOOT_V1_0_BOOTCONTROL_H
 
diff --git a/boot/1.0/default/service.cpp b/boot/1.0/default/service.cpp
index 247e40e..f3996ef 100644
--- a/boot/1.0/default/service.cpp
+++ b/boot/1.0/default/service.cpp
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 #define LOG_TAG "android.hardware.boot@1.0-service"
 
 #include <android/hardware/boot/1.0/IBootControl.h>
diff --git a/boot/1.0/vts/Android.bp b/boot/1.0/vts/Android.bp
new file mode 100644
index 0000000..7aef46b
--- /dev/null
+++ b/boot/1.0/vts/Android.bp
@@ -0,0 +1,3 @@
+subdirs = [
+    "*"
+]
diff --git a/boot/1.0/vts/Android.mk b/boot/1.0/vts/Android.mk
new file mode 100644
index 0000000..df5dac8
--- /dev/null
+++ b/boot/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/boot/1.0/vts/BootControl.vts b/boot/1.0/vts/BootControl.vts
new file mode 100644
index 0000000..384ae50
--- /dev/null
+++ b/boot/1.0/vts/BootControl.vts
@@ -0,0 +1,93 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IBootControl"
+
+package: "android.hardware.boot"
+
+import: "android.hardware.boot@1.0::types"
+
+interface: {
+    api: {
+        name: "getNumberSlots"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "getCurrentSlot"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "markBootSuccessful"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::boot::V1_0::CommandResult"
+        }
+    }
+
+    api: {
+        name: "setActiveBootSlot"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::boot::V1_0::CommandResult"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "setSlotAsUnbootable"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::boot::V1_0::CommandResult"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "isSlotBootable"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::boot::V1_0::BoolResult"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "isSlotMarkedSuccessful"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::boot::V1_0::BoolResult"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "getSuffix"
+        return_type_hidl: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+}
diff --git a/boot/1.0/vts/functional/Android.bp b/boot/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..714a18b
--- /dev/null
+++ b/boot/1.0/vts/functional/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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_test {
+    name: "boot_hidl_hal_test",
+    gtest: true,
+    srcs: ["boot_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.boot@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/boot/1.0/vts/functional/Android.mk b/boot/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/boot_hidl_hal_test.cpp b/boot/1.0/vts/functional/boot_hidl_hal_test.cpp
new file mode 100644
index 0000000..36142df
--- /dev/null
+++ b/boot/1.0/vts/functional/boot_hidl_hal_test.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "boot_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <cutils/properties.h>
+
+#include <android/hardware/boot/1.0/IBootControl.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::boot::V1_0::IBootControl;
+using ::android::hardware::boot::V1_0::CommandResult;
+using ::android::hardware::boot::V1_0::BoolResult;
+using ::android::hardware::boot::V1_0::Slot;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::sp;
+
+// The main test class for the Boot HIDL HAL.
+class BootHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    boot = IBootControl::getService();
+    ASSERT_NE(boot, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IBootControl> boot;
+};
+
+auto generate_callback(CommandResult *dest) {
+  return [=](CommandResult cr) { *dest = cr; };
+}
+
+// Sanity check Boot::getNumberSlots().
+TEST_F(BootHidlTest, GetNumberSlots) {
+  uint32_t slots = boot->getNumberSlots();
+  EXPECT_LE((uint32_t)2, slots);
+}
+
+// Sanity check Boot::getCurrentSlot().
+TEST_F(BootHidlTest, GetCurrentSlot) {
+  Slot curSlot = boot->getCurrentSlot();
+  uint32_t slots = boot->getNumberSlots();
+  EXPECT_LT(curSlot, slots);
+}
+
+// Sanity check Boot::markBootSuccessful().
+TEST_F(BootHidlTest, MarkBootSuccessful) {
+  CommandResult cr;
+  Return<void> result = boot->markBootSuccessful(generate_callback(&cr));
+  ASSERT_TRUE(result.isOk());
+  if (cr.success) {
+    Slot curSlot = boot->getCurrentSlot();
+    BoolResult ret = boot->isSlotMarkedSuccessful(curSlot);
+    EXPECT_EQ(BoolResult::TRUE, ret);
+  }
+}
+
+// Sanity check Boot::setActiveBootSlot() on good and bad inputs.
+TEST_F(BootHidlTest, SetActiveBootSlot) {
+  for (Slot s = 0; s < 2; s++) {
+    CommandResult cr;
+    Return<void> result = boot->setActiveBootSlot(s, generate_callback(&cr));
+    EXPECT_TRUE(result.isOk());
+  }
+  {
+    // Restore original flags to avoid problems on reboot
+    CommandResult cr;
+    Return <void> result = boot->markBootSuccessful(generate_callback(&cr));
+    EXPECT_TRUE(result.isOk());
+    EXPECT_TRUE(cr.success);
+  }
+  {
+    CommandResult cr;
+    uint32_t slots = boot->getNumberSlots();
+    Return<void> result =
+        boot->setActiveBootSlot(slots, generate_callback(&cr));
+    ASSERT_TRUE(result.isOk());
+    EXPECT_EQ(false, cr.success);
+  }
+}
+
+// Sanity check Boot::setSlotAsUnbootable() on good and bad inputs.
+TEST_F(BootHidlTest, SetSlotAsUnbootable) {
+  {
+    CommandResult cr;
+    Slot curSlot = boot->getCurrentSlot();
+    Slot otherSlot = curSlot ? 0 : 1;
+    Return<void> result =
+        boot->setSlotAsUnbootable(otherSlot, generate_callback(&cr));
+    EXPECT_TRUE(result.isOk());
+    if (cr.success) {
+      EXPECT_EQ(BoolResult::FALSE, boot->isSlotBootable(otherSlot));
+
+      // Restore original flags to avoid problems on reboot
+      result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
+      EXPECT_TRUE(result.isOk());
+      EXPECT_TRUE(cr.success);
+      result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
+      EXPECT_TRUE(result.isOk());
+      EXPECT_TRUE(cr.success);
+      result = boot->markBootSuccessful(generate_callback(&cr));
+      EXPECT_TRUE(result.isOk());
+      EXPECT_TRUE(cr.success);
+    }
+  }
+  {
+    CommandResult cr;
+    uint32_t slots = boot->getNumberSlots();
+    Return<void> result =
+        boot->setSlotAsUnbootable(slots, generate_callback(&cr));
+    EXPECT_TRUE(result.isOk());
+    EXPECT_EQ(false, cr.success);
+  }
+}
+
+// Sanity check Boot::isSlotBootable() on good and bad inputs.
+TEST_F(BootHidlTest, IsSlotBootable) {
+  for (Slot s = 0; s < 2; s++) {
+    EXPECT_NE(BoolResult::INVALID_SLOT, boot->isSlotBootable(s));
+  }
+  uint32_t slots = boot->getNumberSlots();
+  EXPECT_EQ(BoolResult::INVALID_SLOT, boot->isSlotBootable(slots));
+}
+
+// Sanity check Boot::isSlotMarkedSuccessful() on good and bad inputs.
+TEST_F(BootHidlTest, IsSlotMarkedSuccessful) {
+  for (Slot s = 0; s < 2; s++) {
+    EXPECT_NE(BoolResult::INVALID_SLOT, boot->isSlotMarkedSuccessful(s));
+  }
+  uint32_t slots = boot->getNumberSlots();
+  EXPECT_EQ(BoolResult::INVALID_SLOT, boot->isSlotMarkedSuccessful(slots));
+}
+
+// Sanity check Boot::getSuffix() on good and bad inputs.
+TEST_F(BootHidlTest, GetSuffix) {
+  const char *suffixPtr;
+  auto cb = [&](hidl_string suffix) { suffixPtr = suffix.c_str(); };
+  for (Slot i = 0; i < 2; i++) {
+    CommandResult cr;
+    Return<void> result = boot->getSuffix(i, cb);
+    EXPECT_TRUE(result.isOk());
+    char correctSuffix[3];
+    snprintf(correctSuffix, sizeof(correctSuffix), "_%c", 'a' + i);
+    ASSERT_EQ(0, strcmp(suffixPtr, correctSuffix));
+  }
+  {
+    char emptySuffix[] = "";
+    Return<void> result = boot->getSuffix(boot->getNumberSlots(), cb);
+    EXPECT_TRUE(result.isOk());
+    ASSERT_EQ(0, strcmp(emptySuffix, suffixPtr));
+  }
+}
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/boot/1.0/vts/functional/vts/Android.mk b/boot/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/vts/testcases/Android.mk b/boot/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/Android.mk b/boot/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/Android.mk b/boot/1.0/vts/functional/vts/testcases/hal/boot/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/Android.mk b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/Android.mk b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/Android.mk
new file mode 100644
index 0000000..844b93b
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalBootHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/boot/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..bc759bf
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Boot HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalBootHidlTargetTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/boot_hidl_hal_test/boot_hidl_hal_test,
+            _64bit::DATA/nativetest64/boot_hidl_hal_test/boot_hidl_hal_test,
+            "/>
+        <option name="test-config-path" value="vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config" />
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config
new file mode 100644
index 0000000..ebb4d1b
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target/HalBootHidlTargetTest.config
@@ -0,0 +1,20 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [
+        {
+            "module_name": "system/lib64/hw/bootctrl.msm8996",
+            "git_project": {
+                "name": "platform/hardware/qcom/bootctrl",
+                "path": "hardware/qcom/bootctrl"
+            }
+        },
+        {
+            "module_name": "system/lib64/hw/android.hardware.boot@1.0-impl",
+            "git_project": {
+                "name": "platform/hardware/interfaces",
+                "path": "hardware/interfaces"
+            }
+        }
+    ]
+}
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/Android.mk b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..f7414df
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalBootHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/boot/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/AndroidTest.xml b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..dbc6300
--- /dev/null
+++ b/boot/1.0/vts/functional/vts/testcases/hal/boot/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Boot HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalBootHidlTargetProfilingTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/boot_hidl_hal_test/boot_hidl_hal_test,
+            _64bit::DATA/nativetest64/boot_hidl_hal_test/boot_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/boot/1.0/vts/types.vts b/boot/1.0/vts/types.vts
new file mode 100644
index 0000000..ebeaa60
--- /dev/null
+++ b/boot/1.0/vts/types.vts
@@ -0,0 +1,42 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.boot"
+
+
+attribute: {
+    name: "::android::hardware::boot::V1_0::CommandResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "success"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "errMsg"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::boot::V1_0::BoolResult"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FALSE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TRUE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "INVALID_SLOT"
+        scalar_value: {
+            int32_t: -1
+        }
+    }
+}
+
diff --git a/boot/Android.bp b/boot/Android.bp
index bbb3e4b..67af5bb 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -1,4 +1,6 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/vts",
+    "1.0/vts/functional",
 ]
diff --git a/broadcastradio/1.0/Android.bp b/broadcastradio/1.0/Android.bp
new file mode 100644
index 0000000..cf44add
--- /dev/null
+++ b/broadcastradio/1.0/Android.bp
@@ -0,0 +1,80 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.broadcastradio@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.broadcastradio@1.0",
+    srcs: [
+        "types.hal",
+        "IBroadcastRadio.hal",
+        "IBroadcastRadioFactory.hal",
+        "ITuner.hal",
+        "ITunerCallback.hal",
+    ],
+    out: [
+        "android/hardware/broadcastradio/1.0/types.cpp",
+        "android/hardware/broadcastradio/1.0/BroadcastRadioAll.cpp",
+        "android/hardware/broadcastradio/1.0/BroadcastRadioFactoryAll.cpp",
+        "android/hardware/broadcastradio/1.0/TunerAll.cpp",
+        "android/hardware/broadcastradio/1.0/TunerCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.broadcastradio@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.broadcastradio@1.0",
+    srcs: [
+        "types.hal",
+        "IBroadcastRadio.hal",
+        "IBroadcastRadioFactory.hal",
+        "ITuner.hal",
+        "ITunerCallback.hal",
+    ],
+    out: [
+        "android/hardware/broadcastradio/1.0/types.h",
+        "android/hardware/broadcastradio/1.0/IBroadcastRadio.h",
+        "android/hardware/broadcastradio/1.0/IHwBroadcastRadio.h",
+        "android/hardware/broadcastradio/1.0/BnHwBroadcastRadio.h",
+        "android/hardware/broadcastradio/1.0/BpHwBroadcastRadio.h",
+        "android/hardware/broadcastradio/1.0/BsBroadcastRadio.h",
+        "android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h",
+        "android/hardware/broadcastradio/1.0/IHwBroadcastRadioFactory.h",
+        "android/hardware/broadcastradio/1.0/BnHwBroadcastRadioFactory.h",
+        "android/hardware/broadcastradio/1.0/BpHwBroadcastRadioFactory.h",
+        "android/hardware/broadcastradio/1.0/BsBroadcastRadioFactory.h",
+        "android/hardware/broadcastradio/1.0/ITuner.h",
+        "android/hardware/broadcastradio/1.0/IHwTuner.h",
+        "android/hardware/broadcastradio/1.0/BnHwTuner.h",
+        "android/hardware/broadcastradio/1.0/BpHwTuner.h",
+        "android/hardware/broadcastradio/1.0/BsTuner.h",
+        "android/hardware/broadcastradio/1.0/ITunerCallback.h",
+        "android/hardware/broadcastradio/1.0/IHwTunerCallback.h",
+        "android/hardware/broadcastradio/1.0/BnHwTunerCallback.h",
+        "android/hardware/broadcastradio/1.0/BpHwTunerCallback.h",
+        "android/hardware/broadcastradio/1.0/BsTunerCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.broadcastradio@1.0",
+    generated_sources: ["android.hardware.broadcastradio@1.0_genc++"],
+    generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/broadcastradio/1.0/Android.mk b/broadcastradio/1.0/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/IBroadcastRadio.hal b/broadcastradio/1.0/IBroadcastRadio.hal
new file mode 100644
index 0000000..c7fe62d
--- /dev/null
+++ b/broadcastradio/1.0/IBroadcastRadio.hal
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.hardware.broadcastradio@1.0;
+
+import ITunerCallback;
+import ITuner;
+
+interface IBroadcastRadio {
+
+    /*
+     * Retrieve implementation properties.
+     * @return result Operation completion status: OK in case of success,
+     *                NOT_INITIALIZED in case of initialization error.
+     * @return properties A Properties structure containing implementation
+     *                    description and capabilities.
+     */
+    getProperties() generates (Result result, Properties properties);
+
+    /*
+     * Open a tuner interface for the requested configuration.
+     * If no other tuner is opened, this will power on the radio hardware.
+     * The hardware must be powered down when all tuner interface are released.
+     * @param config A BandConfig struct containing the band configuration to apply
+     * @param audio True if this tuner must be used for live radio listening and
+     *              should be connected to the radio audio source.
+     * @param callback the callback interface
+     * @return result Operation completion status: OK in case of success,
+     *                INVALID_ARGUMENTS if configuration requested is invalid,
+     *                INVALID_STATE if called out of sequence
+     * @return tuner The interface to control the tuner
+     *
+     * Callback ITunerCallback.ConfigChanged MUST be called once the
+     * configuration is applied or a failure occurs or after a time out.
+     */
+    openTuner(BandConfig config, bool audio, ITunerCallback callback)
+                generates (Result result, ITuner tuner);
+};
diff --git a/broadcastradio/1.0/IBroadcastRadioFactory.hal b/broadcastradio/1.0/IBroadcastRadioFactory.hal
new file mode 100644
index 0000000..82a97c4
--- /dev/null
+++ b/broadcastradio/1.0/IBroadcastRadioFactory.hal
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.hardware.broadcastradio@1.0;
+
+import IBroadcastRadio;
+
+interface IBroadcastRadioFactory {
+
+    /*
+     * Connects to a broadcast radio HAL module for a given class
+     * (AM/FM, Satellite, DAB).
+     *
+     * @param classId Class of the module to connect to .
+     * @return retval operation completion status. Returns INVALID_ARGUMENTS
+     *         if there is no corresponding hardware module found,
+     *         NOT_INITIALIZED if an error occurred while opening the hardware
+     *         module.
+     * @return result the interface for the created module.
+     */
+    connectModule(Class classId)
+      generates (Result retval, IBroadcastRadio result);
+};
diff --git a/broadcastradio/1.0/ITuner.hal b/broadcastradio/1.0/ITuner.hal
new file mode 100644
index 0000000..ae4b284
--- /dev/null
+++ b/broadcastradio/1.0/ITuner.hal
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2015 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.broadcastradio@1.0;
+
+import ITunerCallback;
+
+interface ITuner {
+
+    /*
+     * Apply current radio band configuration (band, range, channel spacing...).
+     * Automatically cancels pending scan, step or tune.
+     * ITunerCallback.configChange() method MUST be called once the
+     * configuration is applied or a failure occurs or after a time out.
+     * @param config The band configuration to apply.
+     * @return result OK if configuration could be applied
+     *                NOT_INITIALIZED in case of initialization error.
+     *                INVALID_ARGUMENTS if configuration requested is invalid
+     *
+     */
+    setConfiguration(BandConfig config) generates(Result result);
+
+    /*
+     * Retrieve current radio band configuration.
+     * @return result OK if valid configuration is returned,
+     *                NOT_INITIALIZED in case of initialization error.
+     * @param config Current band configuration
+     */
+    getConfiguration() generates(Result result, BandConfig config);
+
+    /*
+     * Start scanning up to next valid station.
+     * Shall be called only when a valid configuration has been applied.
+     * Automatically cancels pending scan, step or tune.
+     * ITunerCallback.tuneComplete() MUST be called once locked on a station
+     * or after a time out or full band scan if no station found.
+     * The status should indicate if a valid station is tuned or not.
+     * @param direction UP or DOWN.
+     * @param skipSubChannel valid for HD radio or digital radios only:
+     *                       ignore sub channels (e.g SPS for HD radio).
+     * @return result OK if scan successfully started
+     *                INVALID_STATE if called out of sequence
+     *                NOT_INITIALIZED if another error occurs
+     */
+    scan(Direction direction, bool skipSubChannel) generates(Result result);
+
+    /*
+     * Move one channel spacing up or down.
+     * Must be called when a valid configuration has been applied.
+     * Automatically cancels pending scan, step or tune.
+     * ITunerCallback.tuneComplete() MUST be called once locked on a station
+     * or after a time out or full band scan if no station found.
+     * The status should indicate if a valid station is tuned or not.
+     * @param direction UP or DOWN.
+     * @param skipSubChannel valid for HD radio or digital radios only:
+     *                       ignore sub channels (e.g SPS for HD radio).
+     * @return result OK if scan successfully started
+     *                INVALID_STATE if called out of sequence
+     *                NOT_INITIALIZED if another error occurs
+     */
+    step(Direction direction, bool skipSubChannel) generates(Result result);
+
+    /*
+     * Tune to specified channel.
+     * Must be called when a valid configuration has been applied.
+     * Automatically cancels pending scan, step or tune.
+     * ITunerCallback.tuneComplete() MUST be called once locked on a station
+     * or after a time out or full band scan if no station found.
+     * The status should indicate if a valid station is tuned or not.
+     * @param channel Channel to tune to. A frequency in kHz for AM/FM/HD Radio
+     *                bands.
+     * @param subChannel Valid for HD radio or digital radios only
+     *                   (e.g SPS number for HD radio)..
+     * @return result OK if scan successfully started
+     *                INVALID_ARGUMENTS if invalid arguments are passed
+     *                INVALID_STATE if called out of sequence
+     *                NOT_INITIALIZED if another error occurs
+     */
+    tune(uint32_t channel, uint32_t subChannel) generates(Result result);
+
+    /*
+     * Cancel a scan, step or tune operation.
+     * Shall be called only while a scan, step or tune operation is pending.
+     * ITunerCallback.tuneComplete() MUST NOT be sent by the HAL.
+     * @return result OK if scan successfully started
+     *                INVALID_STATE if called out of sequence
+     *                NOT_INITIALIZED if another error occurs
+     */
+    cancel() generates(Result result);
+
+    /*
+     * Retrieve current station information.
+     * @return result OK if scan successfully started
+     *                NOT_INITIALIZED if another error occurs
+     * @return info Current program information.
+     */
+    getProgramInformation() generates(Result result, ProgramInfo info);
+};
diff --git a/broadcastradio/1.0/ITunerCallback.hal b/broadcastradio/1.0/ITunerCallback.hal
new file mode 100644
index 0000000..a7e1260
--- /dev/null
+++ b/broadcastradio/1.0/ITunerCallback.hal
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package android.hardware.broadcastradio@1.0;
+
+
+interface ITunerCallback {
+
+    /*
+     * Method called by the HAL when a HW failure occurs.
+     * The framework MUST close the ITuner interface and open a new one.
+     */
+    oneway hardwareFailure();
+
+    /*
+     * Method called by the HAL when a new configuration is applied
+     * in response to IDevice.openTuner() or ITuner.setConfiguration().
+     * @param result OK if the configuration has been applied,
+     *               INVALID_ARGUMENTS if not or TIMEOUT in case of time out.
+     * @param config A BandConfig structure describing the new configuration
+     *               applied.
+     */
+    oneway configChange(Result result, BandConfig config);
+
+    /*
+     * Method called by the HAL when a tuning operation completes
+     * following a step(), scan() or tune() command.
+     * @param result OK if tune succeeded or TIMEOUT in case of time out.
+     * @param info A ProgramInfo structure describing the tuned station.
+     */
+    oneway tuneComplete(Result result, ProgramInfo info);
+
+    /*
+     * Method called by the HAL when a frequency switch occurs.
+     * @param info A ProgramInfo structure describing the new tuned station.
+     */
+    oneway afSwitch(ProgramInfo info);
+
+    /*
+     * Method called by the HAL when the antenna connection state changes.
+     * @param connected True if the antenna is connected, false otherwise.
+     */
+    oneway antennaStateChange(bool connected);
+
+    /*
+     * Method called by the HAL when a traffic announcement starts or
+     * stops.
+     * @param active True if the announcement starts, false if it stops.
+     */
+    oneway trafficAnnouncement(bool active);
+
+    /*
+     * Method called by the HAL when an emergency announcement starts
+     * or stops.
+     * @param active True if the announcement starts, false if it stops.
+     */
+    oneway emergencyAnnouncement(bool active);
+
+    /*
+     * Method called by the HAL when metadata for current station
+     * are updated.
+     * @param channel The channel the metadata is associated with.
+     * @param subChannel The sub channel the metadata is associated with.
+     * @param metadata A list of all updated metada.
+     */
+    oneway newMetadata(uint32_t channel, uint32_t subChannel, vec<MetaData>  metadata);
+};
\ No newline at end of file
diff --git a/broadcastradio/1.0/default/Android.mk b/broadcastradio/1.0/default/Android.mk
new file mode 100644
index 0000000..734a0e1
--- /dev/null
+++ b/broadcastradio/1.0/default/Android.mk
@@ -0,0 +1,28 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.broadcastradio@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    BroadcastRadio.cpp \
+    BroadcastRadioFactory.cpp \
+    Tuner.cpp \
+    Utils.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog \
+    libhardware \
+    android.hardware.broadcastradio@1.0 \
+    libradio_metadata
+
+ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
+LOCAL_MULTILIB := 32
+else
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/broadcastradio/1.0/default/BroadcastRadio.cpp b/broadcastradio/1.0/default/BroadcastRadio.cpp
new file mode 100644
index 0000000..45ffdb2
--- /dev/null
+++ b/broadcastradio/1.0/default/BroadcastRadio.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadio"
+//#define LOG_NDEBUG 0
+
+#include <log/log.h>
+
+#include <hardware/radio.h>
+
+#include "BroadcastRadio.h"
+#include "Tuner.h"
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+BroadcastRadio::BroadcastRadio(Class classId)
+    : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
+{
+}
+
+BroadcastRadio::~BroadcastRadio()
+{
+    if (mHwDevice != NULL) {
+        radio_hw_device_close(mHwDevice);
+    }
+}
+
+void BroadcastRadio::onFirstRef()
+{
+    const hw_module_t *mod;
+    int rc;
+    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
+
+    mHwDevice = NULL;
+    const char *classString = Utils::getClassString(mClassId);
+    if (classString == NULL) {
+        ALOGE("invalid class ID %d", mClassId);
+        mStatus = Result::INVALID_ARGUMENTS;
+        return;
+    }
+
+    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
+          __FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
+
+    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load radio module %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
+        return;
+    }
+    rc = radio_hw_device_open(mod, &mHwDevice);
+    if (rc != 0) {
+        ALOGE("couldn't open radio hw device in %s.%s (%s)",
+              RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
+        mHwDevice = NULL;
+        return;
+    }
+    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
+        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
+        radio_hw_device_close(mHwDevice);
+        mHwDevice = NULL;
+    } else {
+        mStatus = Result::OK;
+    }
+}
+
+int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
+{
+    ALOGV("%s", __FUNCTION__);
+    if (mHwDevice == NULL) {
+        return -ENODEV;
+    }
+    if (halTuner == 0) {
+        return -EINVAL;
+    }
+    return mHwDevice->close_tuner(mHwDevice, halTuner);
+}
+
+
+// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
+{
+    int rc;
+    radio_hal_properties_t halProperties;
+    Properties properties;
+
+    if (mHwDevice == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+    rc = mHwDevice->get_properties(mHwDevice, &halProperties);
+    if (rc == 0) {
+        Utils::convertPropertiesFromHal(&properties, &halProperties);
+    }
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), properties);
+    return Void();
+}
+
+Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
+                                       const sp<ITunerCallback>& callback, openTuner_cb _hidl_cb)
+{
+    sp<Tuner> tunerImpl = new Tuner(callback, this);
+
+    radio_hal_band_config_t halConfig;
+    const struct radio_tuner *halTuner;
+    Utils::convertBandConfigToHal(&halConfig, &config);
+    int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio,
+                                   Tuner::callback, tunerImpl.get(),
+                                   &halTuner);
+    if (rc == 0) {
+        tunerImpl->setHalTuner(halTuner);
+    }
+
+    _hidl_cb(Utils::convertHalResult(rc), tunerImpl);
+    return Void();
+}
+
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/BroadcastRadio.h b/broadcastradio/1.0/default/BroadcastRadio.h
new file mode 100644
index 0000000..6764d82
--- /dev/null
+++ b/broadcastradio/1.0/default/BroadcastRadio.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIO_H
+
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
+#include <hidl/Status.h>
+#include <hardware/radio.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadio : public IBroadcastRadio {
+
+            BroadcastRadio(Class classId);
+
+            // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadio follow.
+            Return<void> getProperties(getProperties_cb _hidl_cb)  override;
+            Return<void> openTuner(const BandConfig& config, bool audio,
+                                   const sp<ITunerCallback>& callback,
+                                   openTuner_cb _hidl_cb)  override;
+
+
+    // RefBase
+    virtual void onFirstRef();
+
+            Result  initCheck() { return mStatus; }
+            int closeHalTuner(const struct radio_tuner *halTuner);
+
+private:
+    virtual     ~BroadcastRadio();
+
+    static const char * sClassModuleNames[];
+
+    Result convertHalResult(int rc);
+    void convertBandConfigFromHal(BandConfig *config,
+            const radio_hal_band_config_t *halConfig);
+    void convertPropertiesFromHal(Properties *properties,
+            const radio_hal_properties_t *halProperties);
+    void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
+            const BandConfig *config);
+
+    Result                   mStatus;
+    Class                    mClassId;
+    struct radio_hw_device  *mHwDevice;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIO_H
diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.cpp b/broadcastradio/1.0/default/BroadcastRadioFactory.cpp
new file mode 100644
index 0000000..d5d214c
--- /dev/null
+++ b/broadcastradio/1.0/default/BroadcastRadioFactory.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+#include "BroadcastRadioFactory.h"
+#include "BroadcastRadio.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
+Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb)  {
+    sp<BroadcastRadio> impl = new BroadcastRadio(classId);
+    Result retval = Result::NOT_INITIALIZED;
+    if (impl != 0) {
+        retval = impl->initCheck();
+    }
+    _hidl_cb(retval, impl);
+    return Void();
+}
+
+
+IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
+    return new BroadcastRadioFactory();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/BroadcastRadioFactory.h b/broadcastradio/1.0/default/BroadcastRadioFactory.h
new file mode 100644
index 0000000..97f7f55
--- /dev/null
+++ b/broadcastradio/1.0/default/BroadcastRadioFactory.h
@@ -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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIOFACTORY_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIOFACTORY_H
+
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadioFactory : public IBroadcastRadioFactory {
+    // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
+    Return<void> connectModule(Class classId, connectModule_cb _hidl_cb)  override;
+
+};
+
+extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_BROADCASTRADIOFACTORY_H
diff --git a/broadcastradio/1.0/default/Tuner.cpp b/broadcastradio/1.0/default/Tuner.cpp
new file mode 100644
index 0000000..b564d5a
--- /dev/null
+++ b/broadcastradio/1.0/default/Tuner.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Tuner"
+//#define LOG_NDEBUG 0
+
+#include <log/log.h>
+
+#include "BroadcastRadio.h"
+#include "Tuner.h"
+#include "Utils.h"
+#include <system/radio_metadata.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+void Tuner::onCallback(radio_hal_event_t *halEvent)
+{
+    BandConfig config;
+    ProgramInfo info;
+    hidl_vec<MetaData> metadata;
+
+    if (mCallback != 0) {
+        switch(halEvent->type) {
+        case RADIO_EVENT_CONFIG:
+            Utils::convertBandConfigFromHal(&config, &halEvent->config);
+            mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
+            break;
+        case RADIO_EVENT_ANTENNA:
+            mCallback->antennaStateChange(halEvent->on);
+            break;
+        case RADIO_EVENT_TUNED:
+            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
+            mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info);
+            break;
+        case RADIO_EVENT_METADATA: {
+            uint32_t channel;
+            uint32_t sub_channel;
+            if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
+                Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
+                mCallback->newMetadata(channel, sub_channel, metadata);
+            }
+            } break;
+        case RADIO_EVENT_TA:
+            mCallback->trafficAnnouncement(halEvent->on);
+            break;
+        case RADIO_EVENT_AF_SWITCH:
+            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
+            mCallback->afSwitch(info);
+            break;
+        case RADIO_EVENT_EA:
+            mCallback->emergencyAnnouncement(halEvent->on);
+            break;
+        case RADIO_EVENT_HW_FAILURE:
+        default:
+            mCallback->hardwareFailure();
+            break;
+        }
+    }
+}
+
+//static
+void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
+{
+    wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
+    sp<Tuner> tuner = weak.promote();
+    if (tuner == 0) return;
+    tuner->onCallback(halEvent);
+}
+
+Tuner::Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
+    : mHalTuner(NULL), mCallback(callback), mParentDevice(parentDevice)
+{
+    ALOGV("%s", __FUNCTION__);
+}
+
+
+Tuner::~Tuner()
+{
+    ALOGV("%s", __FUNCTION__);
+    const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
+    if (parentDevice != 0) {
+        parentDevice->closeHalTuner(mHalTuner);
+    }
+}
+
+// Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
+Return<Result> Tuner::setConfiguration(const BandConfig& config)  {
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    radio_hal_band_config_t halConfig;
+    Utils::convertBandConfigToHal(&halConfig, &config);
+    int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
+    return Utils::convertHalResult(rc);
+}
+
+Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb)  {
+    int rc;
+    radio_hal_band_config_t halConfig;
+    BandConfig config;
+
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+    rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
+    if (rc == 0) {
+        Utils::convertBandConfigFromHal(&config, &halConfig);
+    }
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), config);
+    return Void();
+}
+
+Return<Result> Tuner::scan(Direction direction, bool skipSubChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::step(Direction direction, bool skipSubChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel)  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
+    return Utils::convertHalResult(rc);
+}
+
+Return<Result> Tuner::cancel()  {
+    if (mHalTuner == NULL) {
+        return Utils::convertHalResult(-ENODEV);
+    }
+    int rc = mHalTuner->cancel(mHalTuner);
+    return Utils::convertHalResult(rc);
+}
+
+Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb)  {
+    int rc;
+    radio_program_info_t halInfo;
+    ProgramInfo info;
+
+    ALOGV("%s", __FUNCTION__);
+    if (mHalTuner == NULL) {
+        rc = -ENODEV;
+        goto exit;
+    }
+
+    radio_metadata_allocate(&halInfo.metadata, 0, 0);
+    rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
+    if (rc == 0) {
+        Utils::convertProgramInfoFromHal(&info, &halInfo);
+    }
+    radio_metadata_deallocate(halInfo.metadata);
+
+exit:
+    _hidl_cb(Utils::convertHalResult(rc), info);
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/Tuner.h b/broadcastradio/1.0/default/Tuner.h
new file mode 100644
index 0000000..bfdd4f4
--- /dev/null
+++ b/broadcastradio/1.0/default/Tuner.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_TUNER_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_TUNER_H
+
+#include <android/hardware/broadcastradio/1.0/ITuner.h>
+#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
+#include <hidl/Status.h>
+#include <hardware/radio.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+struct BroadcastRadio;
+
+struct Tuner : public ITuner {
+
+    Tuner(const sp<ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
+
+    // Methods from ::android::hardware::broadcastradio::V1_0::ITuner follow.
+    Return<Result> setConfiguration(const BandConfig& config)  override;
+    Return<void> getConfiguration(getConfiguration_cb _hidl_cb)  override;
+    Return<Result> scan(Direction direction, bool skipSubChannel)  override;
+    Return<Result> step(Direction direction, bool skipSubChannel)  override;
+    Return<Result> tune(uint32_t channel, uint32_t subChannel)  override;
+    Return<Result> cancel()  override;
+    Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb)  override;
+
+    static void callback(radio_hal_event_t *halEvent, void *cookie);
+           void onCallback(radio_hal_event_t *halEvent);
+
+    void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
+    const struct radio_tuner *getHalTuner() { return mHalTuner; }
+
+ private:
+    ~Tuner();
+
+    const struct radio_tuner    *mHalTuner;
+    const sp<ITunerCallback>     mCallback;
+    const wp<BroadcastRadio>     mParentDevice;
+};
+
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_TUNER_H
diff --git a/broadcastradio/1.0/default/Utils.cpp b/broadcastradio/1.0/default/Utils.cpp
new file mode 100644
index 0000000..8776222
--- /dev/null
+++ b/broadcastradio/1.0/default/Utils.cpp
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioHalUtils"
+//#define LOG_NDEBUG 0
+
+#include <log/log.h>
+#include <utils/misc.h>
+#include <system/radio_metadata.h>
+
+#include "Utils.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+const char *Utils::sClassModuleNames[] = {
+    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
+    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
+    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
+};
+
+// make sure HIDL enum values are aligned with legacy values
+static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
+              "AM/FM class mismatch with legacy");
+static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
+              "SAT class mismatch with legacy");
+static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
+              "DT class mismatch with legacy");
+
+static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
+              "AM band mismatch with legacy");
+static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
+              "FM band mismatch with legacy");
+static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
+              "AM HD band mismatch with legacy");
+static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
+              "FM HD band mismatch with legacy");
+
+static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
+              "RDS NONE mismatch with legacy");
+static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
+              "RDS WORLD mismatch with legacy");
+static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
+              "RDS US mismatch with legacy");
+
+static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
+              "De-emphasis 50 mismatch with legacy");
+static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
+              "De-emphasis 75 mismatch with legacy");
+
+static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
+              "Direction Up mismatch with legacy");
+static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
+              "Direction Up mismatch with legacy");
+
+static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
+              "Metadata type INVALID mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
+              "Metadata type INT mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
+              "Metadata type TEXT mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
+              "Metadata type RAW mismatch with legacy");
+static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
+              "Metadata type CLOCK mismatch with legacy");
+
+static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
+              "Metadata key INVALID mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
+              "Metadata key RDS_PI mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
+              "Metadata key RDS_PS mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
+              "Metadata key RDS_PTY mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
+              "Metadata key RBDS_PTY mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
+              "Metadata key RDS_RT mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
+              "Metadata key TITLE mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
+              "Metadata key ARTIST mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
+              "Metadata key ALBUM mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
+              "Metadata key GENRE mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
+              "Metadata key ICON mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
+              "Metadata key ART mismatch with legacy");
+static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
+              "Metadata key CLOCK mismatch with legacy");
+
+
+//static
+const char * Utils::getClassString(Class ClassId)
+{
+    int id = static_cast<int>(ClassId);
+
+    if ((id < 0) ||
+            (id >= NELEM(sClassModuleNames))) {
+        ALOGE("invalid class ID %d", id);
+        return NULL;
+    }
+    return sClassModuleNames[id];
+}
+
+//static
+Result Utils::convertHalResult(int rc)
+{
+    switch (rc) {
+        case 0:
+            return Result::OK;
+        case -EINVAL:
+            return Result::INVALID_ARGUMENTS;
+        case -ENOSYS:
+            return Result::INVALID_STATE;
+        case -ETIMEDOUT:
+            return Result::TIMEOUT;
+        case -ENODEV:
+        default:
+            return Result::NOT_INITIALIZED;
+    }
+}
+
+//static
+void Utils::convertBandConfigFromHal(
+        BandConfig *config,
+        const radio_hal_band_config_t *halConfig)
+{
+
+    config->type = static_cast<Band>(halConfig->type);
+    config->antennaConnected = halConfig->antenna_connected;
+    config->lowerLimit = halConfig->lower_limit;
+    config->upperLimit = halConfig->upper_limit;
+    config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
+                                       halConfig->num_spacings * sizeof(uint32_t));
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    config->spacings.resize(halConfig->num_spacings);
+
+    if (config->type == Band::FM) {
+        config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
+        config->ext.fm.stereo = halConfig->fm.stereo;
+        config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
+        config->ext.fm.ta = halConfig->fm.ta;
+        config->ext.fm.af = halConfig->fm.af;
+        config->ext.fm.ea = halConfig->fm.ea;
+    } else {
+        config->ext.am.stereo = halConfig->am.stereo;
+    }
+}
+
+//static
+void Utils::convertPropertiesFromHal(
+        Properties *properties,
+        const radio_hal_properties_t *halProperties)
+{
+    properties->classId = static_cast<Class>(halProperties->class_id);
+    properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
+    properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
+    properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
+    properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
+    properties->numTuners = halProperties->num_tuners;
+    properties->numAudioSources = halProperties->num_audio_sources;
+    properties->supportsCapture = halProperties->supports_capture;
+
+    BandConfig *bands =
+            new BandConfig[halProperties->num_bands];
+    for (size_t i = 0; i < halProperties->num_bands; i++) {
+        convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
+    }
+    properties->bands.setToExternal(bands, halProperties->num_bands);
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    properties->bands.resize(halProperties->num_bands);
+    delete[] bands;
+}
+
+//static
+void Utils::convertBandConfigToHal(
+        radio_hal_band_config_t *halConfig,
+        const BandConfig *config)
+{
+
+    halConfig->type = static_cast<radio_band_t>(config->type);
+    halConfig->antenna_connected = config->antennaConnected;
+    halConfig->lower_limit = config->lowerLimit;
+    halConfig->upper_limit = config->upperLimit;
+    halConfig->num_spacings = config->spacings.size();
+    if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
+        halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
+    }
+    memcpy(halConfig->spacings, config->spacings.data(),
+           sizeof(uint32_t) * halConfig->num_spacings);
+
+    if (config->type == Band::FM) {
+        halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
+        halConfig->fm.stereo = config->ext.fm.stereo;
+        halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
+        halConfig->fm.ta = config->ext.fm.ta;
+        halConfig->fm.af = config->ext.fm.af;
+        halConfig->fm.ea = config->ext.fm.ea;
+    } else {
+        halConfig->am.stereo = config->ext.am.stereo;
+    }
+}
+
+
+//static
+void Utils::convertProgramInfoFromHal(ProgramInfo *info,
+                                      radio_program_info_t *halInfo)
+{
+    info->channel = halInfo->channel;
+    info->subChannel = halInfo->sub_channel;
+    info->tuned = halInfo->tuned;
+    info->stereo = halInfo->stereo;
+    info->digital = halInfo->digital;
+    info->signalStrength = halInfo->signal_strength;
+    convertMetaDataFromHal(info->metadata, halInfo->metadata);
+}
+
+//static
+int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
+                                   radio_metadata_t *halMetadata)
+{
+    if (halMetadata == NULL) {
+        ALOGE("Invalid argument: halMetadata is NULL");
+        return 0;
+    }
+
+    int count = radio_metadata_get_count(halMetadata);
+    if (count <= 0) {
+        return count;
+    }
+    MetaData *newMetadata =
+            new MetaData[count];
+    int outCount = 0;
+    for (int i = 0; i < count; i++) {
+        radio_metadata_key_t key;
+        radio_metadata_type_t type;
+        void *value;
+        size_t size;
+        if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
+                size == 0) {
+            continue;
+        }
+        switch (type) {
+            case RADIO_METADATA_TYPE_INT: {
+                newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
+            } break;
+            case RADIO_METADATA_TYPE_TEXT: {
+                newMetadata[outCount].stringValue = static_cast<char *>(value);
+            } break;
+            case RADIO_METADATA_TYPE_RAW: {
+                newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
+                // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+                newMetadata[outCount].rawValue.resize(size);
+            } break;
+            case RADIO_METADATA_TYPE_CLOCK: {
+                  radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
+                  newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
+                          clock->utc_seconds_since_epoch;
+                  newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
+                          clock->timezone_offset_in_minutes;
+            } break;
+        }
+        newMetadata[outCount].type = static_cast<MetadataType>(type);
+        newMetadata[outCount].key = static_cast<MetadataKey>(key);
+        outCount++;
+    }
+    metadata.setToExternal(newMetadata, outCount);
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    metadata.resize(outCount);
+    return outCount;
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.0/default/Utils.h b/broadcastradio/1.0/default/Utils.h
new file mode 100644
index 0000000..4ef22a5
--- /dev/null
+++ b/broadcastradio/1.0/default/Utils.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
+
+#include <android/hardware/broadcastradio/1.0/types.h>
+#include <hardware/radio.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_0 {
+namespace implementation {
+
+class Utils {
+public:
+    static const char * getClassString(Class ClassId);
+    static Result convertHalResult(int rc);
+    static void convertBandConfigFromHal(BandConfig *config,
+            const radio_hal_band_config_t *halConfig);
+    static void convertPropertiesFromHal(Properties *properties,
+            const radio_hal_properties_t *halProperties);
+    static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
+            const BandConfig *config);
+    static void convertProgramInfoFromHal(ProgramInfo *info,
+                                          radio_program_info_t *halInfo);
+    static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
+                                       radio_metadata_t *halMetadata);
+private:
+    static const char * sClassModuleNames[];
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_0_UTILS_H
diff --git a/broadcastradio/1.0/types.hal b/broadcastradio/1.0/types.hal
new file mode 100644
index 0000000..d8b2da3
--- /dev/null
+++ b/broadcastradio/1.0/types.hal
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+package android.hardware.broadcastradio@1.0;
+
+enum Result : int32_t {
+    OK,
+    NOT_INITIALIZED,
+    INVALID_ARGUMENTS,
+    INVALID_STATE,
+    TIMEOUT,
+};
+
+/*
+ * Radio hardware module class. A given radio hardware module HAL is of one
+ * class only. The platform can not have more than one hardware module of
+ * each class. Current version of the framework only supports RADIO_CLASS_AM_FM.
+ */
+enum Class : uint32_t {
+    /* FM (including HD radio) and AM */
+    AM_FM = 0,
+    /* Satellite Radio */
+    SAT   = 1,
+    /* Digital Radio (DAB) */
+    DT    = 2,
+};
+
+/* value for field "type" of radio band described in struct radio_hal_band_config */
+enum Band : uint32_t {
+    /* Amplitude Modulation band: LW, MW, SW */
+    AM     = 0,
+    /* Frequency Modulation band: FM */
+    FM     = 1,
+    /* FM HD Radio / DRM (IBOC) */
+    FM_HD  = 2,
+    /* AM HD Radio / DRM (IBOC) */
+    AM_HD  = 3,
+};
+
+/* RDS variant implemented. A struct FmBandConfig can list none or several. */
+enum Rds : uint32_t {
+    NONE   = 0,
+    WORLD  = (1<<0),
+    US = (1<<1),
+};
+
+
+/* FM deemphasis variant implemented.
+ * A struct FmBandConfig can list one or more. */
+enum Deemphasis : uint32_t {
+    D50   = (1<<0),
+    D75   = (1<<1),
+};
+
+/* Scanning direction for scan() and step() tuner APIs */
+enum Direction : uint32_t {
+    UP,
+    DOWN
+};
+
+/* Unique handle allocated to a radio module */
+typedef uint32_t Handle;
+
+
+/* Additional attributes for an FM band configuration */
+struct FmBandConfig {
+    /* deemphasis variant */
+    Deemphasis deemphasis;
+    /* stereo supported */
+    bool       stereo;
+    /* RDS variants supported */
+    Rds        rds;
+    /* Traffic Announcement supported */
+    bool       ta;
+    /* Alternate Frequency supported */
+    bool       af;
+    /* Emergency announcements supported */
+    bool       ea;
+};
+
+/* Additional attributes for an AM band configuration */
+struct AmBandConfig {
+    /* Stereo supported */
+    bool       stereo;
+};
+
+/* Radio band configuration. Describes a given band supported by the radio
+ * module. The HAL can expose only one band per type with the the maximum range
+ * supported and all options. The framework will derive the actual regions were
+ * this module can operate and expose separate band configurations for
+ * applications to chose from. */
+struct BandConfig {
+    Band type;
+    bool antennaConnected;
+    uint32_t lowerLimit;
+    uint32_t upperLimit;
+    vec<uint32_t> spacings;
+    union Ext {
+        FmBandConfig fm;
+        AmBandConfig am;
+    } ext;
+};
+
+/* Exposes properties of a given hardware radio module.
+ * NOTE: current framework implementation supports only one audio source
+ * (num_audio_sources = 1). The source corresponds to AUDIO_DEVICE_IN_FM_TUNER.
+ * If more than one tuner is supported (num_tuners > 1), only one can be
+ * connected to the audio source. */
+struct Properties {
+    /* Class of this module. E.g AM_FM */
+    Class           classId;
+    /* implementor name */
+    string          implementor;
+    /* product name */
+    string          product;
+    /* product version */
+    string          version;
+    /* serial number (for subscription services) */
+    string          serial;
+    /* number of tuners controllable independently */
+    uint32_t        numTuners;
+    /* number of audio sources driven simultaneously */
+    uint32_t        numAudioSources;
+    /* the hardware supports capture of audio source from audio HAL */
+    bool            supportsCapture;
+    vec<BandConfig> bands; /* band descriptors */
+};
+
+enum MetadataType : int32_t {
+    INVALID    = -1,
+    /* Signed 32 bit integer  */
+    INT        = 0,
+    /* String */
+    TEXT       = 1,
+    /* Raw binary data (icon or art)
+       This data must be transparent to the android framework */
+    RAW        = 2,
+    /* clock data, see MetaDataClock */
+    CLOCK      = 3,
+};
+
+enum MetadataKey : int32_t {
+    INVALID      = -1,
+    /* RDS PI                 - string  */
+    RDS_PI       = 0,
+    /* RDS PS                 - string */
+    RDS_PS       = 1,
+    /* RDS PTY                - int32_t  */
+    RDS_PTY      = 2,
+    /* RBDS PTY               - int32_t  */
+    RBDS_PTY     = 3,
+    /* RDS RT                 - string  */
+    RDS_RT       = 4,
+    /* Song title             - string  */
+    TITLE        = 5,
+    /* Artist name            - string  */
+    ARTIST       = 6,
+    /* Album name             - string  */
+    ALBUM        = 7,
+    /* Musical genre          - string  */
+    GENRE        = 8,
+    /* Station icon           - raw  */
+    ICON         = 9,
+    /* Album art              - raw  */
+    ART          = 10,
+    /* Clock                  - MetaDataClock */
+    CLOCK        = 11,
+};
+
+struct MetaDataClock {
+     /* Seconds since epoch at GMT + 0. */
+    uint64_t utcSecondsSinceEpoch;
+    /* Minutes offset from the GMT. */
+    int32_t timezoneOffsetInMinutes;
+};
+
+struct MetaData {
+    MetadataType type;
+    MetadataKey key;
+    /* Value used for type MetadataType.INT */
+    int32_t intValue;
+    /* Value used for type MetadataType.CLOCK */
+    MetaDataClock  clockValue;
+    /* Value used for type MetadataType.TEXT */
+    string  stringValue;
+    /* Value used for type MetadataType.RAW */
+    vec<uint8_t> rawValue;
+};
+
+
+/* Radio program information. Returned by the HAL with event RADIO_EVENT_TUNED.
+ * Contains information on currently tuned channel.
+ */
+struct ProgramInfo {
+    uint32_t     channel;   /* current channel. (e.g kHz for band type AM_FM) */
+    uint32_t     subChannel; /* current sub channel. (FM_HD) */
+    bool         tuned;     /* tuned to a program or not */
+    bool         stereo;    /* program is stereo or not */
+    bool         digital;   /* digital program or not (e.g HD Radio program) */
+    uint32_t     signalStrength; /* signal strength from 0 to 100 */
+    vec<MetaData> metadata; /* non empty if meta data are present (e.g PTY, song title ...) */
+};
+
diff --git a/broadcastradio/1.0/vts/Android.mk b/broadcastradio/1.0/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..0edfcab
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/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_test {
+    name: "broadcastradio_hidl_hal_test",
+    gtest: true,
+    srcs: ["broadcastradio_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.broadcastradio@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/broadcastradio/1.0/vts/functional/Android.mk b/broadcastradio/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/broadcastradio_hidl_hal_test.cpp b/broadcastradio/1.0/vts/functional/broadcastradio_hidl_hal_test.cpp
new file mode 100644
index 0000000..bcbfbb7
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/broadcastradio_hidl_hal_test.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "BroadcastRadioHidlHalTest"
+#include <gtest/gtest.h>
+#include <android-base/logging.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/threads.h>
+
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/1.0/ITuner.h>
+#include <android/hardware/broadcastradio/1.0/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.0/types.h>
+
+
+using ::android::sp;
+using ::android::Mutex;
+using ::android::Condition;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+using ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory;
+using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
+using ::android::hardware::broadcastradio::V1_0::ITuner;
+using ::android::hardware::broadcastradio::V1_0::ITunerCallback;
+using ::android::hardware::broadcastradio::V1_0::Result;
+using ::android::hardware::broadcastradio::V1_0::Class;
+using ::android::hardware::broadcastradio::V1_0::Properties;
+using ::android::hardware::broadcastradio::V1_0::BandConfig;
+using ::android::hardware::broadcastradio::V1_0::Direction;
+using ::android::hardware::broadcastradio::V1_0::ProgramInfo;
+using ::android::hardware::broadcastradio::V1_0::MetaData;
+
+
+// The main test class for Sound Trigger HIDL HAL.
+
+class BroadcastRadioHidlTest : public ::testing::Test {
+ protected:
+    virtual void SetUp() override {
+        bool getStub = false;
+        char getsubProperty[PROPERTY_VALUE_MAX];
+        if (property_get("vts.hidl.get_stub", getsubProperty, "") > 0) {
+            if (!strcmp(getsubProperty, "true") ||
+                    !strcmp(getsubProperty, "True") ||
+                    !strcmp(getsubProperty, "1")) {
+                getStub = true;
+            }
+        }
+        sp<IBroadcastRadioFactory> factory =
+              IBroadcastRadioFactory::getService("broadcastradio", getStub);
+        if (factory != 0) {
+            factory->connectModule(Class::AM_FM,
+                             [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
+                if (retval == Result::OK) {
+                  mRadio = result;
+                }
+            });
+        }
+        mTunerCallback = new MyCallback(this);
+        ASSERT_NE(nullptr, mRadio.get());
+        ASSERT_EQ(!getStub, mRadio->isRemote());
+        ASSERT_NE(nullptr, mTunerCallback.get());
+    }
+
+    virtual void TearDown() override {
+        mTuner.clear();
+        mRadio.clear();
+    }
+
+    class MyCallback : public ITunerCallback {
+     public:
+
+        // ITunerCallback methods (see doc in ITunerCallback.hal)
+        virtual Return<void> hardwareFailure() {
+            ALOGI("%s", __FUNCTION__);
+            mParentTest->onHwFailureCallback();
+            return Void();
+        }
+
+        virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
+            ALOGI("%s result %d", __FUNCTION__, result);
+            mParentTest->onResultCallback(result);
+            return Void();
+        }
+
+        virtual Return<void> tuneComplete(Result result, const ProgramInfo& info __unused) {
+            ALOGI("%s result %d", __FUNCTION__, result);
+            mParentTest->onResultCallback(result);
+            return Void();
+        }
+
+        virtual Return<void> afSwitch(const ProgramInfo& info __unused) {
+            return Void();
+        }
+
+        virtual Return<void> antennaStateChange(bool connected) {
+            ALOGI("%s connected %d", __FUNCTION__, connected);
+            return Void();
+        }
+
+        virtual Return<void> trafficAnnouncement(bool active) {
+            ALOGI("%s active %d", __FUNCTION__, active);
+            return Void();
+        }
+
+        virtual Return<void> emergencyAnnouncement(bool active) {
+            ALOGI("%s active %d", __FUNCTION__, active);
+            return Void();
+        }
+
+        virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
+                           const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
+            ALOGI("%s", __FUNCTION__);
+            return Void();
+        }
+
+                MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
+
+     private:
+        // BroadcastRadioHidlTest instance to which callbacks will be notified.
+        BroadcastRadioHidlTest *mParentTest;
+    };
+
+
+    /**
+     * Method called by MyCallback when a callback with no status or boolean value is received
+     */
+    void onCallback() {
+        Mutex::Autolock _l(mLock);
+        onCallback_l();
+    }
+
+    /**
+     * Method called by MyCallback when hardwareFailure() callback is received
+     */
+    void onHwFailureCallback() {
+        Mutex::Autolock _l(mLock);
+        mHwFailure = true;
+        onCallback_l();
+    }
+
+    /**
+     * Method called by MyCallback when a callback with status is received
+     */
+    void onResultCallback(Result result) {
+        Mutex::Autolock _l(mLock);
+        mResultCallbackData = result;
+        onCallback_l();
+    }
+
+    /**
+     * Method called by MyCallback when a boolean indication is received
+     */
+    void onBoolCallback(bool result) {
+        Mutex::Autolock _l(mLock);
+        mBoolCallbackData = result;
+        onCallback_l();
+    }
+
+
+        BroadcastRadioHidlTest() :
+            mCallbackCalled(false), mBoolCallbackData(false),
+            mResultCallbackData(Result::OK), mHwFailure(false) {}
+
+    void onCallback_l() {
+        if (!mCallbackCalled) {
+            mCallbackCalled = true;
+            mCallbackCond.broadcast();
+        }
+    }
+
+
+    bool waitForCallback(nsecs_t reltime = 0) {
+        Mutex::Autolock _l(mLock);
+        nsecs_t endTime = systemTime() + reltime;
+        while (!mCallbackCalled) {
+            if (reltime == 0) {
+                mCallbackCond.wait(mLock);
+            } else {
+                nsecs_t now = systemTime();
+                if (now > endTime) {
+                    return false;
+                }
+                mCallbackCond.waitRelative(mLock, endTime - now);
+            }
+        }
+        return true;
+    }
+
+    bool getProperties();
+    bool openTuner();
+    bool checkAntenna();
+
+    static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
+    static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
+
+    sp<IBroadcastRadio> mRadio;
+    Properties mHalProperties;
+    sp<ITuner> mTuner;
+    sp<MyCallback> mTunerCallback;
+    Mutex mLock;
+    Condition mCallbackCond;
+    bool mCallbackCalled;
+    bool mBoolCallbackData;
+    Result mResultCallbackData;
+    bool mHwFailure;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class BroadcastRadioHidlEnvironment : public ::testing::Environment {
+ public:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+};
+
+bool BroadcastRadioHidlTest::getProperties()
+{
+    if (mHalProperties.bands.size() == 0) {
+        Result halResult = Result::NOT_INITIALIZED;
+        Return<void> hidlReturn =
+                mRadio->getProperties([&](Result result, const Properties& properties) {
+                        halResult = result;
+                        if (result == Result::OK) {
+                            mHalProperties = properties;
+                        }
+                    });
+
+        EXPECT_TRUE(hidlReturn.isOk());
+        EXPECT_EQ(Result::OK, halResult);
+        EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
+        EXPECT_GT(mHalProperties.numTuners, 0u);
+        EXPECT_GT(mHalProperties.bands.size(), 0u);
+    }
+    return mHalProperties.bands.size() > 0;
+}
+
+bool BroadcastRadioHidlTest::openTuner()
+{
+    if (!getProperties()) {
+        return false;
+    }
+    if (mTuner.get() == nullptr) {
+        Result halResult = Result::NOT_INITIALIZED;
+        Return<void> hidlReturn =
+                mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
+                                  [&](Result result, const sp<ITuner>& tuner) {
+                        halResult = result;
+                        if (result == Result::OK) {
+                            mTuner = tuner;
+                        }
+                    });
+        EXPECT_TRUE(hidlReturn.isOk());
+        EXPECT_EQ(Result::OK, halResult);
+        EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
+    }
+    EXPECT_NE(nullptr, mTuner.get());
+    return nullptr != mTuner.get();
+}
+
+bool BroadcastRadioHidlTest::checkAntenna()
+{
+    BandConfig halConfig;
+    Result halResult = Result::NOT_INITIALIZED;
+    Return<void> hidlReturn =
+            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
+                halResult = result;
+                if (result == Result::OK) {
+                    halConfig = config;
+                }
+            });
+
+    return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
+}
+
+
+/**
+ * Test IBroadcastRadio::getProperties() method
+ *
+ * Verifies that:
+ *  - the HAL implements the method
+ *  - the method returns 0 (no error)
+ *  - the implementation class is AM_FM
+ *  - the implementation supports at least one tuner
+ *  - the implementation supports at one band
+ */
+TEST_F(BroadcastRadioHidlTest, GetProperties) {
+    EXPECT_EQ(true, getProperties());
+}
+
+/**
+ * Test IBroadcastRadio::openTuner() method
+ *
+ * Verifies that:
+ *  - the HAL implements the method
+ *  - the method returns 0 (no error) and a valid ITuner interface
+ */
+TEST_F(BroadcastRadioHidlTest, OpenTuner) {
+    EXPECT_EQ(true, openTuner());
+}
+
+/**
+ * Test ITuner::setConfiguration() and getConfiguration methods
+ *
+ * Verifies that:
+ *  - the HAL implements both methods
+ *  - the methods return 0 (no error)
+ *  - the configuration callback is received within kConfigCallbacktimeoutNs ns
+ *  - the configuration read back from HAl has the same class Id
+ */
+TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
+    ASSERT_EQ(true, openTuner());
+    // test setConfiguration
+    mCallbackCalled = false;
+    Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kConfigCallbacktimeoutNs));
+    EXPECT_EQ(Result::OK, mResultCallbackData);
+
+    // test getConfiguration
+    BandConfig halConfig;
+    Result halResult;
+    Return<void> hidlReturn =
+            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
+                halResult = result;
+                if (result == Result::OK) {
+                    halConfig = config;
+                }
+            });
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_EQ(Result::OK, halResult);
+    EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
+}
+
+/**
+ * Test ITuner::scan
+ *
+ * Verifies that:
+ *  - the HAL implements the method
+ *  - the method returns 0 (no error)
+ *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
+ */
+TEST_F(BroadcastRadioHidlTest, Scan) {
+    ASSERT_EQ(true, openTuner());
+    ASSERT_TRUE(checkAntenna());
+    // test scan UP
+    mCallbackCalled = false;
+    Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
+
+    // test scan DOWN
+    mCallbackCalled = false;
+    hidlResult = mTuner->scan(Direction::DOWN, true);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
+}
+
+/**
+ * Test ITuner::step
+ *
+ * Verifies that:
+ *  - the HAL implements the method
+ *  - the method returns 0 (no error)
+ *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
+ */
+TEST_F(BroadcastRadioHidlTest, Step) {
+    ASSERT_EQ(true, openTuner());
+    ASSERT_TRUE(checkAntenna());
+    // test step UP
+    mCallbackCalled = false;
+    Return<Result> hidlResult = mTuner->step(Direction::UP, true);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
+
+    // test step DOWN
+    mCallbackCalled = false;
+    hidlResult = mTuner->step(Direction::DOWN, true);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
+}
+
+/**
+ * Test ITuner::tune,  getProgramInformation and cancel methods
+ *
+ * Verifies that:
+ *  - the HAL implements the methods
+ *  - the methods return 0 (no error)
+ *  - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
+ */
+TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
+    ASSERT_EQ(true, openTuner());
+    ASSERT_TRUE(checkAntenna());
+
+    // test tune
+    ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
+    ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
+
+    // test scan UP
+    uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
+    uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
+    uint32_t spacing = mHalProperties.bands[0].spacings[0];
+
+    uint32_t channel =
+            lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
+    mCallbackCalled = false;
+    mResultCallbackData = Result::NOT_INITIALIZED;
+    Return<Result> hidlResult = mTuner->tune(channel, 0);
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_EQ(true, waitForCallback(kTuneCallbacktimeoutNs));
+
+    // test getProgramInformation
+    ProgramInfo halInfo;
+    Result halResult = Result::NOT_INITIALIZED;
+    Return<void> hidlReturn = mTuner->getProgramInformation(
+        [&](Result result, const ProgramInfo& info) {
+            halResult = result;
+            if (result == Result::OK) {
+                halInfo = info;
+            }
+        });
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_EQ(Result::OK, halResult);
+    if (mResultCallbackData == Result::OK) {
+        EXPECT_EQ(true, halInfo.tuned);
+        EXPECT_LE(halInfo.channel, upperLimit);
+        EXPECT_GE(halInfo.channel, lowerLimit);
+    } else {
+        EXPECT_EQ(false, halInfo.tuned);
+    }
+
+    // test cancel
+    mTuner->tune(lowerLimit, 0);
+    hidlResult = mTuner->cancel();
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, hidlResult);
+}
+
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/broadcastradio/1.0/vts/functional/vts/Android.mk b/broadcastradio/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/Android.mk b/broadcastradio/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/hal/Android.mk b/broadcastradio/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/Android.mk b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/Android.mk b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/Android.mk b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/Android.mk
new file mode 100644
index 0000000..153dcd6
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalBroadcastRadioHidlTargetBasicTest
+VTS_CONFIG_SRC_DIR := testcases/hal/broadcastradio/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/AndroidTest.xml b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..4c03855
--- /dev/null
+++ b/broadcastradio/1.0/vts/functional/vts/testcases/hal/broadcastradio/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS broadcast radio HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalBroadcastRadioHidlTargetBasicTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/broadcastradio_hidl_hal_test/broadcastradio_hidl_hal_test,
+            _64bit::DATA/nativetest64/broadcastradio_hidl_hal_test/broadcastradio_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+    </test>
+</configuration>
diff --git a/broadcastradio/Android.bp b/broadcastradio/Android.bp
new file mode 100644
index 0000000..33f70eb
--- /dev/null
+++ b/broadcastradio/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/vts/functional",
+]
diff --git a/camera/Android.bp b/camera/Android.bp
new file mode 100644
index 0000000..e379e49
--- /dev/null
+++ b/camera/Android.bp
@@ -0,0 +1,12 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "common/1.0",
+    "common/1.0/default",
+    "device/1.0",
+    "device/3.2",
+    "device/3.2/default",
+    "metadata/3.2",
+    "provider/2.4",
+    "provider/2.4/default",
+    "provider/2.4/vts/functional",
+]
diff --git a/camera/README.md b/camera/README.md
new file mode 100644
index 0000000..8ce3352
--- /dev/null
+++ b/camera/README.md
@@ -0,0 +1,12 @@
+## Camera HALs ##
+---
+
+## Overview: ##
+
+The camera.* HAL tree is used by the Android camera service to discover and
+operate camera devices available on the device.
+
+More details and versioning information can be found within each particular HAL.
+
+More complete information about the Android camera HAL and subsystem can be found at
+[source.android.com](http://source.android.com/devices/camera/index.html).
diff --git a/camera/common/1.0/Android.bp b/camera/common/1.0/Android.bp
new file mode 100644
index 0000000..49098c4
--- /dev/null
+++ b/camera/common/1.0/Android.bp
@@ -0,0 +1,46 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.camera.common@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.common@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/camera/common/1.0/types.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.common@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.common@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/camera/common/1.0/types.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.common@1.0",
+    generated_sources: ["android.hardware.camera.common@1.0_genc++"],
+    generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/camera/common/1.0/Android.mk b/camera/common/1.0/Android.mk
new file mode 100644
index 0000000..2e68dc0
--- /dev/null
+++ b/camera/common/1.0/Android.mk
@@ -0,0 +1,372 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.camera.common@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (CameraDeviceStatus)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraDeviceStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraDeviceStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataType)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraMetadataType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraMetadataType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraResourceCost)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraResourceCost.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraResourceCost
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TagBoundaryId)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TagBoundaryId.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TagBoundaryId
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TorchMode)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TorchMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TorchMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TorchModeStatus)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TorchModeStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TorchModeStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VendorTag)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/VendorTag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.VendorTag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VendorTagSection)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/VendorTagSection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.VendorTagSection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.camera.common@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (CameraDeviceStatus)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraDeviceStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraDeviceStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataType)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraMetadataType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraMetadataType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraResourceCost)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/CameraResourceCost.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.CameraResourceCost
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TagBoundaryId)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TagBoundaryId.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TagBoundaryId
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TorchMode)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TorchMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TorchMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TorchModeStatus)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/TorchModeStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.TorchModeStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VendorTag)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/VendorTag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.VendorTag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VendorTagSection)
+#
+GEN := $(intermediates)/android/hardware/camera/common/V1_0/VendorTagSection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.common@1.0::types.VendorTagSection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
new file mode 100644
index 0000000..af0ff6e
--- /dev/null
+++ b/camera/common/1.0/default/Android.bp
@@ -0,0 +1,15 @@
+cc_library_static {
+    name: "android.hardware.camera.common@1.0-helper",
+    srcs: ["CameraModule.cpp", "CameraMetadata.cpp", "VendorTagDescriptor.cpp"],
+    cflags: [
+        "-Werror",
+        "-Wextra",
+        "-Wall",
+    ],
+    shared_libs: [
+        "liblog",
+        "libhardware",
+        "libcamera_metadata"],
+    include_dirs: ["system/media/private/camera/include"],
+    export_include_dirs : ["include"]
+}
diff --git a/camera/common/1.0/default/CameraMetadata.cpp b/camera/common/1.0/default/CameraMetadata.cpp
new file mode 100644
index 0000000..44c2040
--- /dev/null
+++ b/camera/common/1.0/default/CameraMetadata.cpp
@@ -0,0 +1,568 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+
+#define LOG_TAG "CamComm1.0-MD"
+#include <utils/Log.h>
+#include <utils/Errors.h>
+
+#include "CameraMetadata.h"
+#include "VendorTagDescriptor.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+#define ALIGN_TO(val, alignment) \
+    (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
+
+CameraMetadata::CameraMetadata() :
+        mBuffer(NULL), mLocked(false) {
+}
+
+CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) :
+        mLocked(false)
+{
+    mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity);
+}
+
+CameraMetadata::CameraMetadata(const CameraMetadata &other) :
+        mLocked(false) {
+    mBuffer = clone_camera_metadata(other.mBuffer);
+}
+
+CameraMetadata::CameraMetadata(camera_metadata_t *buffer) :
+        mBuffer(NULL), mLocked(false) {
+    acquire(buffer);
+}
+
+CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) {
+    return operator=(other.mBuffer);
+}
+
+CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
+    if (mLocked) {
+        ALOGE("%s: Assignment to a locked CameraMetadata!", __FUNCTION__);
+        return *this;
+    }
+
+    if (CC_LIKELY(buffer != mBuffer)) {
+        camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
+        clear();
+        mBuffer = newBuffer;
+    }
+    return *this;
+}
+
+CameraMetadata::~CameraMetadata() {
+    mLocked = false;
+    clear();
+}
+
+const camera_metadata_t* CameraMetadata::getAndLock() const {
+    mLocked = true;
+    return mBuffer;
+}
+
+status_t CameraMetadata::unlock(const camera_metadata_t *buffer) const {
+    if (!mLocked) {
+        ALOGE("%s: Can't unlock a non-locked CameraMetadata!", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if (buffer != mBuffer) {
+        ALOGE("%s: Can't unlock CameraMetadata with wrong pointer!",
+                __FUNCTION__);
+        return BAD_VALUE;
+    }
+    mLocked = false;
+    return OK;
+}
+
+camera_metadata_t* CameraMetadata::release() {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return NULL;
+    }
+    camera_metadata_t *released = mBuffer;
+    mBuffer = NULL;
+    return released;
+}
+
+void CameraMetadata::clear() {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return;
+    }
+    if (mBuffer) {
+        free_camera_metadata(mBuffer);
+        mBuffer = NULL;
+    }
+}
+
+void CameraMetadata::acquire(camera_metadata_t *buffer) {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return;
+    }
+    clear();
+    mBuffer = buffer;
+
+    ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK,
+             "%s: Failed to validate metadata structure %p",
+             __FUNCTION__, buffer);
+}
+
+void CameraMetadata::acquire(CameraMetadata &other) {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return;
+    }
+    acquire(other.release());
+}
+
+status_t CameraMetadata::append(const CameraMetadata &other) {
+    return append(other.mBuffer);
+}
+
+status_t CameraMetadata::append(const camera_metadata_t* other) {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    size_t extraEntries = get_camera_metadata_entry_count(other);
+    size_t extraData = get_camera_metadata_data_count(other);
+    resizeIfNeeded(extraEntries, extraData);
+
+    return append_camera_metadata(mBuffer, other);
+}
+
+size_t CameraMetadata::entryCount() const {
+    return (mBuffer == NULL) ? 0 :
+            get_camera_metadata_entry_count(mBuffer);
+}
+
+bool CameraMetadata::isEmpty() const {
+    return entryCount() == 0;
+}
+
+status_t CameraMetadata::sort() {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    return sort_camera_metadata(mBuffer);
+}
+
+status_t CameraMetadata::checkType(uint32_t tag, uint8_t expectedType) {
+    int tagType = get_camera_metadata_tag_type(tag);
+    if ( CC_UNLIKELY(tagType == -1)) {
+        ALOGE("Update metadata entry: Unknown tag %d", tag);
+        return INVALID_OPERATION;
+    }
+    if ( CC_UNLIKELY(tagType != expectedType) ) {
+        ALOGE("Mismatched tag type when updating entry %s (%d) of type %s; "
+                "got type %s data instead ",
+                get_camera_metadata_tag_name(tag), tag,
+                camera_metadata_type_names[tagType],
+                camera_metadata_type_names[expectedType]);
+        return INVALID_OPERATION;
+    }
+    return OK;
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const int32_t *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_INT32)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const uint8_t *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const float *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_FLOAT)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const int64_t *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_INT64)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const double *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_DOUBLE)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const camera_metadata_rational_t *data, size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_RATIONAL)) != OK) {
+        return res;
+    }
+    return updateImpl(tag, (const void*)data, data_count);
+}
+
+status_t CameraMetadata::update(uint32_t tag,
+        const String8 &string) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(tag, TYPE_BYTE)) != OK) {
+        return res;
+    }
+    // string.size() doesn't count the null termination character.
+    return updateImpl(tag, (const void*)string.string(), string.size() + 1);
+}
+
+status_t CameraMetadata::update(const camera_metadata_ro_entry &entry) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    if ( (res = checkType(entry.tag, entry.type)) != OK) {
+        return res;
+    }
+    return updateImpl(entry.tag, (const void*)entry.data.u8, entry.count);
+}
+
+status_t CameraMetadata::updateImpl(uint32_t tag, const void *data,
+        size_t data_count) {
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    int type = get_camera_metadata_tag_type(tag);
+    if (type == -1) {
+        ALOGE("%s: Tag %d not found", __FUNCTION__, tag);
+        return BAD_VALUE;
+    }
+    // Safety check - ensure that data isn't pointing to this metadata, since
+    // that would get invalidated if a resize is needed
+    size_t bufferSize = get_camera_metadata_size(mBuffer);
+    uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
+    uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
+    if (dataAddr > bufAddr && dataAddr < (bufAddr + bufferSize)) {
+        ALOGE("%s: Update attempted with data from the same metadata buffer!",
+                __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+
+    size_t data_size = calculate_camera_metadata_entry_data_size(type,
+            data_count);
+
+    res = resizeIfNeeded(1, data_size);
+
+    if (res == OK) {
+        camera_metadata_entry_t entry;
+        res = find_camera_metadata_entry(mBuffer, tag, &entry);
+        if (res == NAME_NOT_FOUND) {
+            res = add_camera_metadata_entry(mBuffer,
+                    tag, data, data_count);
+        } else if (res == OK) {
+            res = update_camera_metadata_entry(mBuffer,
+                    entry.index, data, data_count, NULL);
+        }
+    }
+
+    if (res != OK) {
+        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
+                __FUNCTION__, get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+    }
+
+    IF_ALOGV() {
+        ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) !=
+                 OK,
+
+                 "%s: Failed to validate metadata structure after update %p",
+                 __FUNCTION__, mBuffer);
+    }
+
+    return res;
+}
+
+bool CameraMetadata::exists(uint32_t tag) const {
+    camera_metadata_ro_entry entry;
+    return find_camera_metadata_ro_entry(mBuffer, tag, &entry) == 0;
+}
+
+camera_metadata_entry_t CameraMetadata::find(uint32_t tag) {
+    status_t res;
+    camera_metadata_entry entry;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        entry.count = 0;
+        return entry;
+    }
+    res = find_camera_metadata_entry(mBuffer, tag, &entry);
+    if (CC_UNLIKELY( res != OK )) {
+        entry.count = 0;
+        entry.data.u8 = NULL;
+    }
+    return entry;
+}
+
+camera_metadata_ro_entry_t CameraMetadata::find(uint32_t tag) const {
+    status_t res;
+    camera_metadata_ro_entry entry;
+    res = find_camera_metadata_ro_entry(mBuffer, tag, &entry);
+    if (CC_UNLIKELY( res != OK )) {
+        entry.count = 0;
+        entry.data.u8 = NULL;
+    }
+    return entry;
+}
+
+status_t CameraMetadata::erase(uint32_t tag) {
+    camera_metadata_entry_t entry;
+    status_t res;
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    res = find_camera_metadata_entry(mBuffer, tag, &entry);
+    if (res == NAME_NOT_FOUND) {
+        return OK;
+    } else if (res != OK) {
+        ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
+                __FUNCTION__,
+                get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+        return res;
+    }
+    res = delete_camera_metadata_entry(mBuffer, entry.index);
+    if (res != OK) {
+        ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
+                __FUNCTION__,
+                get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+    }
+    return res;
+}
+
+void CameraMetadata::dump(int fd, int verbosity, int indentation) const {
+    dump_indented_camera_metadata(mBuffer, fd, verbosity, indentation);
+}
+
+status_t CameraMetadata::resizeIfNeeded(size_t extraEntries, size_t extraData) {
+    if (mBuffer == NULL) {
+        mBuffer = allocate_camera_metadata(extraEntries * 2, extraData * 2);
+        if (mBuffer == NULL) {
+            ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
+            return NO_MEMORY;
+        }
+    } else {
+        size_t currentEntryCount = get_camera_metadata_entry_count(mBuffer);
+        size_t currentEntryCap = get_camera_metadata_entry_capacity(mBuffer);
+        size_t newEntryCount = currentEntryCount +
+                extraEntries;
+        newEntryCount = (newEntryCount > currentEntryCap) ?
+                newEntryCount * 2 : currentEntryCap;
+
+        size_t currentDataCount = get_camera_metadata_data_count(mBuffer);
+        size_t currentDataCap = get_camera_metadata_data_capacity(mBuffer);
+        size_t newDataCount = currentDataCount +
+                extraData;
+        newDataCount = (newDataCount > currentDataCap) ?
+                newDataCount * 2 : currentDataCap;
+
+        if (newEntryCount > currentEntryCap ||
+                newDataCount > currentDataCap) {
+            camera_metadata_t *oldBuffer = mBuffer;
+            mBuffer = allocate_camera_metadata(newEntryCount,
+                    newDataCount);
+            if (mBuffer == NULL) {
+                ALOGE("%s: Can't allocate larger metadata buffer", __FUNCTION__);
+                return NO_MEMORY;
+            }
+            append_camera_metadata(mBuffer, oldBuffer);
+            free_camera_metadata(oldBuffer);
+        }
+    }
+    return OK;
+}
+
+void CameraMetadata::swap(CameraMetadata& other) {
+    if (mLocked) {
+        ALOGE("%s: CameraMetadata is locked", __FUNCTION__);
+        return;
+    } else if (other.mLocked) {
+        ALOGE("%s: Other CameraMetadata is locked", __FUNCTION__);
+        return;
+    }
+
+    camera_metadata* thisBuf = mBuffer;
+    camera_metadata* otherBuf = other.mBuffer;
+
+    other.mBuffer = thisBuf;
+    mBuffer = otherBuf;
+}
+
+status_t CameraMetadata::getTagFromName(const char *name,
+        const VendorTagDescriptor* vTags, uint32_t *tag) {
+
+    if (name == nullptr || tag == nullptr) return BAD_VALUE;
+
+    size_t nameLength = strlen(name);
+
+    const SortedVector<String8> *vendorSections;
+    size_t vendorSectionCount = 0;
+
+    if (vTags != NULL) {
+        vendorSections = vTags->getAllSectionNames();
+        vendorSectionCount = vendorSections->size();
+    }
+
+    // First, find the section by the longest string match
+    const char *section = NULL;
+    size_t sectionIndex = 0;
+    size_t sectionLength = 0;
+    size_t totalSectionCount = ANDROID_SECTION_COUNT + vendorSectionCount;
+    for (size_t i = 0; i < totalSectionCount; ++i) {
+
+        const char *str = (i < ANDROID_SECTION_COUNT) ? camera_metadata_section_names[i] :
+                (*vendorSections)[i - ANDROID_SECTION_COUNT].string();
+
+        ALOGV("%s: Trying to match against section '%s'", __FUNCTION__, str);
+
+        if (strstr(name, str) == name) { // name begins with the section name
+            size_t strLength = strlen(str);
+
+            ALOGV("%s: Name begins with section name", __FUNCTION__);
+
+            // section name is the longest we've found so far
+            if (section == NULL || sectionLength < strLength) {
+                section = str;
+                sectionIndex = i;
+                sectionLength = strLength;
+
+                ALOGV("%s: Found new best section (%s)", __FUNCTION__, section);
+            }
+        }
+    }
+
+    // TODO: Make above get_camera_metadata_section_from_name ?
+
+    if (section == NULL) {
+        return NAME_NOT_FOUND;
+    } else {
+        ALOGV("%s: Found matched section '%s' (%zu)",
+              __FUNCTION__, section, sectionIndex);
+    }
+
+    // Get the tag name component of the name
+    const char *nameTagName = name + sectionLength + 1; // x.y.z -> z
+    if (sectionLength + 1 >= nameLength) {
+        return BAD_VALUE;
+    }
+
+    // Match rest of name against the tag names in that section only
+    uint32_t candidateTag = 0;
+    if (sectionIndex < ANDROID_SECTION_COUNT) {
+        // Match built-in tags (typically android.*)
+        uint32_t tagBegin, tagEnd; // [tagBegin, tagEnd)
+        tagBegin = camera_metadata_section_bounds[sectionIndex][0];
+        tagEnd = camera_metadata_section_bounds[sectionIndex][1];
+
+        for (candidateTag = tagBegin; candidateTag < tagEnd; ++candidateTag) {
+            const char *tagName = get_camera_metadata_tag_name(candidateTag);
+
+            if (strcmp(nameTagName, tagName) == 0) {
+                ALOGV("%s: Found matched tag '%s' (%d)",
+                      __FUNCTION__, tagName, candidateTag);
+                break;
+            }
+        }
+
+        if (candidateTag == tagEnd) {
+            return NAME_NOT_FOUND;
+        }
+    } else if (vTags != NULL) {
+        // Match vendor tags (typically com.*)
+        const String8 sectionName(section);
+        const String8 tagName(nameTagName);
+
+        status_t res = OK;
+        if ((res = vTags->lookupTag(tagName, sectionName, &candidateTag)) != OK) {
+            return NAME_NOT_FOUND;
+        }
+    }
+
+    *tag = candidateTag;
+    return OK;
+}
+
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
new file mode 100644
index 0000000..5d9ae4d
--- /dev/null
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamComm1.0-CamModule"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Trace.h>
+
+#include "CameraModule.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+void CameraModule::deriveCameraCharacteristicsKeys(
+        uint32_t deviceVersion, CameraMetadata &chars) {
+    ATRACE_CALL();
+
+    Vector<int32_t> derivedCharKeys;
+    Vector<int32_t> derivedRequestKeys;
+    Vector<int32_t> derivedResultKeys;
+    // Keys added in HAL3.3
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+        Vector<uint8_t> controlModes;
+        uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
+        data = ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE;
+        chars.update(ANDROID_CONTROL_AWB_LOCK_AVAILABLE, &data, /*count*/1);
+        controlModes.push(ANDROID_CONTROL_MODE_AUTO);
+        camera_metadata_entry entry = chars.find(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+        if (entry.count > 1 || entry.data.u8[0] != ANDROID_CONTROL_SCENE_MODE_DISABLED) {
+            controlModes.push(ANDROID_CONTROL_MODE_USE_SCENE_MODE);
+        }
+
+        // Only advertise CONTROL_OFF mode if 3A manual controls are supported.
+        bool isManualAeSupported = false;
+        bool isManualAfSupported = false;
+        bool isManualAwbSupported = false;
+        entry = chars.find(ANDROID_CONTROL_AE_AVAILABLE_MODES);
+        if (entry.count > 0) {
+            for (size_t i = 0; i < entry.count; i++) {
+                if (entry.data.u8[i] == ANDROID_CONTROL_AE_MODE_OFF) {
+                    isManualAeSupported = true;
+                    break;
+                }
+            }
+        }
+        entry = chars.find(ANDROID_CONTROL_AF_AVAILABLE_MODES);
+        if (entry.count > 0) {
+            for (size_t i = 0; i < entry.count; i++) {
+                if (entry.data.u8[i] == ANDROID_CONTROL_AF_MODE_OFF) {
+                    isManualAfSupported = true;
+                    break;
+                }
+            }
+        }
+        entry = chars.find(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
+        if (entry.count > 0) {
+            for (size_t i = 0; i < entry.count; i++) {
+                if (entry.data.u8[i] == ANDROID_CONTROL_AWB_MODE_OFF) {
+                    isManualAwbSupported = true;
+                    break;
+                }
+            }
+        }
+        if (isManualAeSupported && isManualAfSupported && isManualAwbSupported) {
+            controlModes.push(ANDROID_CONTROL_MODE_OFF);
+        }
+
+        chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+
+        entry = chars.find(ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS);
+        // HAL3.2 devices passing existing CTS test should all support all LSC modes and LSC map
+        bool lensShadingModeSupported = false;
+        if (entry.count > 0) {
+            for (size_t i = 0; i < entry.count; i++) {
+                if (entry.data.i32[i] == ANDROID_SHADING_MODE) {
+                    lensShadingModeSupported = true;
+                    break;
+                }
+            }
+        }
+        Vector<uint8_t> lscModes;
+        Vector<uint8_t> lscMapModes;
+        lscModes.push(ANDROID_SHADING_MODE_FAST);
+        lscModes.push(ANDROID_SHADING_MODE_HIGH_QUALITY);
+        lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF);
+        if (lensShadingModeSupported) {
+            lscModes.push(ANDROID_SHADING_MODE_OFF);
+            lscMapModes.push(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON);
+        }
+        chars.update(ANDROID_SHADING_AVAILABLE_MODES, lscModes);
+        chars.update(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES, lscMapModes);
+
+        derivedCharKeys.push(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
+        derivedCharKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE);
+        derivedCharKeys.push(ANDROID_CONTROL_AVAILABLE_MODES);
+        derivedCharKeys.push(ANDROID_SHADING_AVAILABLE_MODES);
+        derivedCharKeys.push(ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES);
+
+        // Need update android.control.availableHighSpeedVideoConfigurations since HAL3.3
+        // adds batch size to this array.
+        entry = chars.find(ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS);
+        if (entry.count > 0) {
+            Vector<int32_t> highSpeedConfig;
+            for (size_t i = 0; i < entry.count; i += 4) {
+                highSpeedConfig.add(entry.data.i32[i]); // width
+                highSpeedConfig.add(entry.data.i32[i + 1]); // height
+                highSpeedConfig.add(entry.data.i32[i + 2]); // fps_min
+                highSpeedConfig.add(entry.data.i32[i + 3]); // fps_max
+                highSpeedConfig.add(1); // batchSize_max. default to 1 for HAL3.2
+            }
+            chars.update(ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
+                    highSpeedConfig);
+        }
+    }
+
+    // Keys added in HAL3.4
+    if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_4) {
+        // Check if HAL supports RAW_OPAQUE output
+        camera_metadata_entry entry = chars.find(ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS);
+        bool supportRawOpaque = false;
+        bool supportAnyRaw = false;
+        const int STREAM_CONFIGURATION_SIZE = 4;
+        const int STREAM_FORMAT_OFFSET = 0;
+        const int STREAM_WIDTH_OFFSET = 1;
+        const int STREAM_HEIGHT_OFFSET = 2;
+        const int STREAM_IS_INPUT_OFFSET = 3;
+        Vector<int32_t> rawOpaqueSizes;
+
+        for (size_t i=0; i < entry.count; i += STREAM_CONFIGURATION_SIZE) {
+            int32_t format = entry.data.i32[i + STREAM_FORMAT_OFFSET];
+            int32_t width = entry.data.i32[i + STREAM_WIDTH_OFFSET];
+            int32_t height = entry.data.i32[i + STREAM_HEIGHT_OFFSET];
+            int32_t isInput = entry.data.i32[i + STREAM_IS_INPUT_OFFSET];
+            if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    format == HAL_PIXEL_FORMAT_RAW_OPAQUE) {
+                supportRawOpaque = true;
+                rawOpaqueSizes.push(width);
+                rawOpaqueSizes.push(height);
+                // 2 bytes per pixel. This rough estimation is only used when
+                // HAL does not fill in the opaque raw size
+                rawOpaqueSizes.push(width * height *2);
+            }
+            if (isInput == ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT &&
+                    (format == HAL_PIXEL_FORMAT_RAW16 ||
+                     format == HAL_PIXEL_FORMAT_RAW10 ||
+                     format == HAL_PIXEL_FORMAT_RAW12 ||
+                     format == HAL_PIXEL_FORMAT_RAW_OPAQUE)) {
+                supportAnyRaw = true;
+            }
+        }
+
+        if (supportRawOpaque) {
+            entry = chars.find(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
+            if (entry.count == 0) {
+                // Fill in estimated value if HAL does not list it
+                chars.update(ANDROID_SENSOR_OPAQUE_RAW_SIZE, rawOpaqueSizes);
+                derivedCharKeys.push(ANDROID_SENSOR_OPAQUE_RAW_SIZE);
+            }
+        }
+
+        // Check if HAL supports any RAW output, if so, fill in postRawSensitivityBoost range
+        if (supportAnyRaw) {
+            int32_t defaultRange[2] = {100, 100};
+            entry = chars.find(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE);
+            if (entry.count == 0) {
+                // Fill in default value (100, 100)
+                chars.update(
+                        ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
+                        defaultRange, 2);
+                derivedCharKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE);
+                // Actual request/results will be derived by camera device.
+                derivedRequestKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST);
+                derivedResultKeys.push(ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST);
+            }
+        }
+    }
+
+    // Always add a default for the pre-correction active array if the vendor chooses to omit this
+    camera_metadata_entry entry = chars.find(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+    if (entry.count == 0) {
+        Vector<int32_t> preCorrectionArray;
+        entry = chars.find(ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE);
+        preCorrectionArray.appendArray(entry.data.i32, entry.count);
+        chars.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE, preCorrectionArray);
+        derivedCharKeys.push(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE);
+    }
+
+    // Add those newly added keys to AVAILABLE_CHARACTERISTICS_KEYS
+    // This has to be done at this end of this function.
+    if (derivedCharKeys.size() > 0) {
+        appendAvailableKeys(
+                chars, ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, derivedCharKeys);
+    }
+    if (derivedRequestKeys.size() > 0) {
+        appendAvailableKeys(
+                chars, ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, derivedRequestKeys);
+    }
+    if (derivedResultKeys.size() > 0) {
+        appendAvailableKeys(
+                chars, ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, derivedResultKeys);
+    }
+    return;
+}
+
+void CameraModule::appendAvailableKeys(CameraMetadata &chars,
+        int32_t keyTag, const Vector<int32_t>& appendKeys) {
+    camera_metadata_entry entry = chars.find(keyTag);
+    Vector<int32_t> availableKeys;
+    availableKeys.setCapacity(entry.count + appendKeys.size());
+    for (size_t i = 0; i < entry.count; i++) {
+        availableKeys.push(entry.data.i32[i]);
+    }
+    for (size_t i = 0; i < appendKeys.size(); i++) {
+        availableKeys.push(appendKeys[i]);
+    }
+    chars.update(keyTag, availableKeys);
+}
+
+CameraModule::CameraModule(camera_module_t *module) {
+    if (module == NULL) {
+        ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
+        assert(0);
+    }
+    mModule = module;
+}
+
+CameraModule::~CameraModule()
+{
+    while (mCameraInfoMap.size() > 0) {
+        camera_info cameraInfo = mCameraInfoMap.editValueAt(0);
+        if (cameraInfo.static_camera_characteristics != NULL) {
+            free_camera_metadata(
+                    const_cast<camera_metadata_t*>(cameraInfo.static_camera_characteristics));
+        }
+        mCameraInfoMap.removeItemsAt(0);
+    }
+}
+
+int CameraModule::init() {
+    ATRACE_CALL();
+    int res = OK;
+    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 &&
+            mModule->init != NULL) {
+        ATRACE_BEGIN("camera_module->init");
+        res = mModule->init();
+        ATRACE_END();
+    }
+    mCameraInfoMap.setCapacity(getNumberOfCameras());
+    return res;
+}
+
+int CameraModule::getCameraInfo(int cameraId, struct camera_info *info) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mCameraInfoLock);
+    if (cameraId < 0) {
+        ALOGE("%s: Invalid camera ID %d", __FUNCTION__, cameraId);
+        return -EINVAL;
+    }
+
+    // Only override static_camera_characteristics for API2 devices
+    int apiVersion = mModule->common.module_api_version;
+    if (apiVersion < CAMERA_MODULE_API_VERSION_2_0) {
+        int ret;
+        ATRACE_BEGIN("camera_module->get_camera_info");
+        ret = mModule->get_camera_info(cameraId, info);
+        // Fill in this so CameraService won't be confused by
+        // possibly 0 device_version
+        info->device_version = CAMERA_DEVICE_API_VERSION_1_0;
+        ATRACE_END();
+        return ret;
+    }
+
+    ssize_t index = mCameraInfoMap.indexOfKey(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        // Get camera info from raw module and cache it
+        camera_info rawInfo, cameraInfo;
+        ATRACE_BEGIN("camera_module->get_camera_info");
+        int ret = mModule->get_camera_info(cameraId, &rawInfo);
+        ATRACE_END();
+        if (ret != 0) {
+            return ret;
+        }
+        int deviceVersion = rawInfo.device_version;
+        if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_0) {
+            // static_camera_characteristics is invalid
+            *info = rawInfo;
+            return ret;
+        }
+        CameraMetadata m;
+        m = rawInfo.static_camera_characteristics;
+        deriveCameraCharacteristicsKeys(rawInfo.device_version, m);
+        cameraInfo = rawInfo;
+        cameraInfo.static_camera_characteristics = m.release();
+        index = mCameraInfoMap.add(cameraId, cameraInfo);
+    }
+
+    assert(index != NAME_NOT_FOUND);
+    // return the cached camera info
+    *info = mCameraInfoMap[index];
+    return OK;
+}
+
+int CameraModule::getDeviceVersion(int cameraId) {
+    ssize_t index = mDeviceVersionMap.indexOfKey(cameraId);
+    if (index == NAME_NOT_FOUND) {
+        int deviceVersion;
+        if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_0) {
+            struct camera_info info;
+            getCameraInfo(cameraId, &info);
+            deviceVersion = info.device_version;
+        } else {
+            deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+        }
+        index = mDeviceVersionMap.add(cameraId, deviceVersion);
+    }
+    assert(index != NAME_NOT_FOUND);
+    return mDeviceVersionMap[index];
+}
+
+int CameraModule::open(const char* id, struct hw_device_t** device) {
+    int res;
+    ATRACE_BEGIN("camera_module->open");
+    res = filterOpenErrorCode(mModule->common.methods->open(&mModule->common, id, device));
+    ATRACE_END();
+    return res;
+}
+
+bool CameraModule::isOpenLegacyDefined() const {
+    if (getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_3) {
+        return false;
+    }
+    return mModule->open_legacy != NULL;
+}
+
+int CameraModule::openLegacy(
+        const char* id, uint32_t halVersion, struct hw_device_t** device) {
+    int res;
+    ATRACE_BEGIN("camera_module->open_legacy");
+    res = mModule->open_legacy(&mModule->common, id, halVersion, device);
+    ATRACE_END();
+    return res;
+}
+
+int CameraModule::getNumberOfCameras() {
+    int numCameras;
+    ATRACE_BEGIN("camera_module->get_number_of_cameras");
+    numCameras = mModule->get_number_of_cameras();
+    ATRACE_END();
+    return numCameras;
+}
+
+int CameraModule::setCallbacks(const camera_module_callbacks_t *callbacks) {
+    int res;
+    ATRACE_BEGIN("camera_module->set_callbacks");
+    res = mModule->set_callbacks(callbacks);
+    ATRACE_END();
+    return res;
+}
+
+bool CameraModule::isVendorTagDefined() const {
+    return mModule->get_vendor_tag_ops != NULL;
+}
+
+void CameraModule::getVendorTagOps(vendor_tag_ops_t* ops) {
+    if (mModule->get_vendor_tag_ops) {
+        ATRACE_BEGIN("camera_module->get_vendor_tag_ops");
+        mModule->get_vendor_tag_ops(ops);
+        ATRACE_END();
+    }
+}
+
+bool CameraModule::isSetTorchModeSupported() const {
+    if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
+        if (mModule->set_torch_mode == NULL) {
+            ALOGE("%s: Module 2.4 device must support set torch API!",
+                    __FUNCTION__);
+            return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+int CameraModule::setTorchMode(const char* camera_id, bool enable) {
+    int res = INVALID_OPERATION;
+    if (mModule->set_torch_mode != NULL) {
+        ATRACE_BEGIN("camera_module->set_torch_mode");
+        res = mModule->set_torch_mode(camera_id, enable);
+        ATRACE_END();
+    }
+    return res;
+}
+
+status_t CameraModule::filterOpenErrorCode(status_t err) {
+    switch(err) {
+        case NO_ERROR:
+        case -EBUSY:
+        case -EINVAL:
+        case -EUSERS:
+            return err;
+        default:
+            break;
+    }
+    return -ENODEV;
+}
+
+uint16_t CameraModule::getModuleApiVersion() const {
+    return mModule->common.module_api_version;
+}
+
+const char* CameraModule::getModuleName() const {
+    return mModule->common.name;
+}
+
+uint16_t CameraModule::getHalApiVersion() const {
+    return mModule->common.hal_api_version;
+}
+
+const char* CameraModule::getModuleAuthor() const {
+    return mModule->common.author;
+}
+
+void* CameraModule::getDso() {
+    return mModule->common.dso;
+}
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/common/1.0/default/VendorTagDescriptor.cpp b/camera/common/1.0/default/VendorTagDescriptor.cpp
new file mode 100644
index 0000000..db884a8
--- /dev/null
+++ b/camera/common/1.0/default/VendorTagDescriptor.cpp
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamComm1.0-VTDesc"
+
+#include <utils/Errors.h>
+#include <utils/Log.h>
+#include <utils/Mutex.h>
+#include <utils/Vector.h>
+#include <utils/SortedVector.h>
+#include <system/camera_metadata.h>
+#include <camera_metadata_hidden.h>
+
+#include "VendorTagDescriptor.h"
+
+#include <stdio.h>
+#include <string.h>
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace params {
+
+VendorTagDescriptor::~VendorTagDescriptor() {
+    size_t len = mReverseMapping.size();
+    for (size_t i = 0; i < len; ++i)  {
+        delete mReverseMapping[i];
+    }
+}
+
+VendorTagDescriptor::VendorTagDescriptor() :
+        mTagCount(0),
+        mVendorOps() {
+}
+
+VendorTagDescriptor::VendorTagDescriptor(const VendorTagDescriptor& src) {
+    copyFrom(src);
+}
+
+VendorTagDescriptor& VendorTagDescriptor::operator=(const VendorTagDescriptor& rhs) {
+    copyFrom(rhs);
+    return *this;
+}
+
+void VendorTagDescriptor::copyFrom(const VendorTagDescriptor& src) {
+    if (this == &src) return;
+
+    size_t len = mReverseMapping.size();
+    for (size_t i = 0; i < len; ++i) {
+        delete mReverseMapping[i];
+    }
+    mReverseMapping.clear();
+
+    len = src.mReverseMapping.size();
+    // Have to copy KeyedVectors inside mReverseMapping
+    for (size_t i = 0; i < len; ++i) {
+        KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+        *nameMapper = *(src.mReverseMapping.valueAt(i));
+        mReverseMapping.add(src.mReverseMapping.keyAt(i), nameMapper);
+    }
+    // Everything else is simple
+    mTagToNameMap = src.mTagToNameMap;
+    mTagToSectionMap = src.mTagToSectionMap;
+    mTagToTypeMap = src.mTagToTypeMap;
+    mSections = src.mSections;
+    mTagCount = src.mTagCount;
+    mVendorOps = src.mVendorOps;
+}
+
+int VendorTagDescriptor::getTagCount() const {
+    size_t size = mTagToNameMap.size();
+    if (size == 0) {
+        return VENDOR_TAG_COUNT_ERR;
+    }
+    return size;
+}
+
+void VendorTagDescriptor::getTagArray(uint32_t* tagArray) const {
+    size_t size = mTagToNameMap.size();
+    for (size_t i = 0; i < size; ++i) {
+        tagArray[i] = mTagToNameMap.keyAt(i);
+    }
+}
+
+const char* VendorTagDescriptor::getSectionName(uint32_t tag) const {
+    ssize_t index = mTagToSectionMap.indexOfKey(tag);
+    if (index < 0) {
+        return VENDOR_SECTION_NAME_ERR;
+    }
+    return mSections[mTagToSectionMap.valueAt(index)].string();
+}
+
+ssize_t VendorTagDescriptor::getSectionIndex(uint32_t tag) const {
+    return mTagToSectionMap.valueFor(tag);
+}
+
+const char* VendorTagDescriptor::getTagName(uint32_t tag) const {
+    ssize_t index = mTagToNameMap.indexOfKey(tag);
+    if (index < 0) {
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return mTagToNameMap.valueAt(index).string();
+}
+
+int VendorTagDescriptor::getTagType(uint32_t tag) const {
+    ssize_t index = mTagToNameMap.indexOfKey(tag);
+    if (index < 0) {
+        return VENDOR_TAG_TYPE_ERR;
+    }
+    return mTagToTypeMap.valueFor(tag);
+}
+
+const SortedVector<String8>* VendorTagDescriptor::getAllSectionNames() const {
+    return &mSections;
+}
+
+status_t VendorTagDescriptor::lookupTag(const String8& name, const String8& section, /*out*/uint32_t* tag) const {
+    ssize_t index = mReverseMapping.indexOfKey(section);
+    if (index < 0) {
+        ALOGE("%s: Section '%s' does not exist.", __FUNCTION__, section.string());
+        return BAD_VALUE;
+    }
+
+    ssize_t nameIndex = mReverseMapping[index]->indexOfKey(name);
+    if (nameIndex < 0) {
+        ALOGE("%s: Tag name '%s' does not exist.", __FUNCTION__, name.string());
+        return BAD_VALUE;
+    }
+
+    if (tag != NULL) {
+        *tag = mReverseMapping[index]->valueAt(nameIndex);
+    }
+    return OK;
+}
+
+void VendorTagDescriptor::dump(int fd, int verbosity, int indentation) const {
+
+    size_t size = mTagToNameMap.size();
+    if (size == 0) {
+        dprintf(fd, "%*sDumping configured vendor tag descriptors: None set\n",
+                indentation, "");
+        return;
+    }
+
+    dprintf(fd, "%*sDumping configured vendor tag descriptors: %zu entries\n",
+            indentation, "", size);
+    for (size_t i = 0; i < size; ++i) {
+        uint32_t tag =  mTagToNameMap.keyAt(i);
+
+        if (verbosity < 1) {
+            dprintf(fd, "%*s0x%x\n", indentation + 2, "", tag);
+            continue;
+        }
+        String8 name = mTagToNameMap.valueAt(i);
+        uint32_t sectionId = mTagToSectionMap.valueFor(tag);
+        String8 sectionName = mSections[sectionId];
+        int type = mTagToTypeMap.valueFor(tag);
+        const char* typeName = (type >= 0 && type < NUM_TYPES) ?
+                camera_metadata_type_names[type] : "UNKNOWN";
+        dprintf(fd, "%*s0x%x (%s) with type %d (%s) defined in section %s\n", indentation + 2,
+            "", tag, name.string(), type, typeName, sectionName.string());
+    }
+
+}
+
+} // namespace params
+} // namespace camera2
+
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+extern "C" {
+
+static int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* v);
+static void vendor_tag_descriptor_get_all_tags(const vendor_tag_ops_t* v, uint32_t* tagArray);
+static const char* vendor_tag_descriptor_get_section_name(const vendor_tag_ops_t* v, uint32_t tag);
+static const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* v, uint32_t tag);
+static int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* v, uint32_t tag);
+
+} /* extern "C" */
+
+static Mutex sLock;
+static sp<VendorTagDescriptor> sGlobalVendorTagDescriptor;
+
+status_t VendorTagDescriptor::createDescriptorFromOps(const vendor_tag_ops_t* vOps,
+            /*out*/
+            sp<VendorTagDescriptor>& descriptor) {
+    if (vOps == NULL) {
+        ALOGE("%s: vendor_tag_ops argument was NULL.", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    int tagCount = vOps->get_tag_count(vOps);
+    if (tagCount < 0 || tagCount > INT32_MAX) {
+        ALOGE("%s: tag count %d from vendor ops is invalid.", __FUNCTION__, tagCount);
+        return BAD_VALUE;
+    }
+
+    Vector<uint32_t> tagArray;
+    LOG_ALWAYS_FATAL_IF(tagArray.resize(tagCount) != tagCount,
+            "%s: too many (%u) vendor tags defined.", __FUNCTION__, tagCount);
+
+    vOps->get_all_tags(vOps, /*out*/tagArray.editArray());
+
+    sp<VendorTagDescriptor> desc = new VendorTagDescriptor();
+    desc->mTagCount = tagCount;
+
+    SortedVector<String8> sections;
+    KeyedVector<uint32_t, String8> tagToSectionMap;
+
+    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
+        uint32_t tag = tagArray[i];
+        if (tag < CAMERA_METADATA_VENDOR_TAG_BOUNDARY) {
+            ALOGE("%s: vendor tag %d not in vendor tag section.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+        const char *tagName = vOps->get_tag_name(vOps, tag);
+        if (tagName == NULL) {
+            ALOGE("%s: no tag name defined for vendor tag %d.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+        desc->mTagToNameMap.add(tag, String8(tagName));
+        const char *sectionName = vOps->get_section_name(vOps, tag);
+        if (sectionName == NULL) {
+            ALOGE("%s: no section name defined for vendor tag %d.", __FUNCTION__, tag);
+            return BAD_VALUE;
+        }
+
+        String8 sectionString(sectionName);
+
+        sections.add(sectionString);
+        tagToSectionMap.add(tag, sectionString);
+
+        int tagType = vOps->get_tag_type(vOps, tag);
+        if (tagType < 0 || tagType >= NUM_TYPES) {
+            ALOGE("%s: tag type %d from vendor ops does not exist.", __FUNCTION__, tagType);
+            return BAD_VALUE;
+        }
+        desc->mTagToTypeMap.add(tag, tagType);
+    }
+
+    desc->mSections = sections;
+
+    for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
+        uint32_t tag = tagArray[i];
+        String8 sectionString = tagToSectionMap.valueFor(tag);
+
+        // Set up tag to section index map
+        ssize_t index = sections.indexOf(sectionString);
+        LOG_ALWAYS_FATAL_IF(index < 0, "index %zd must be non-negative", index);
+        desc->mTagToSectionMap.add(tag, static_cast<uint32_t>(index));
+
+        // Set up reverse mapping
+        ssize_t reverseIndex = -1;
+        if ((reverseIndex = desc->mReverseMapping.indexOfKey(sectionString)) < 0) {
+            KeyedVector<String8, uint32_t>* nameMapper = new KeyedVector<String8, uint32_t>();
+            reverseIndex = desc->mReverseMapping.add(sectionString, nameMapper);
+        }
+        desc->mReverseMapping[reverseIndex]->add(desc->mTagToNameMap.valueFor(tag), tag);
+    }
+
+    descriptor = desc;
+    return OK;
+}
+
+status_t VendorTagDescriptor::setAsGlobalVendorTagDescriptor(const sp<VendorTagDescriptor>& desc) {
+    status_t res = OK;
+    Mutex::Autolock al(sLock);
+    sGlobalVendorTagDescriptor = desc;
+
+    vendor_tag_ops_t* opsPtr = NULL;
+    if (desc != NULL) {
+        opsPtr = &(desc->mVendorOps);
+        opsPtr->get_tag_count = vendor_tag_descriptor_get_tag_count;
+        opsPtr->get_all_tags = vendor_tag_descriptor_get_all_tags;
+        opsPtr->get_section_name = vendor_tag_descriptor_get_section_name;
+        opsPtr->get_tag_name = vendor_tag_descriptor_get_tag_name;
+        opsPtr->get_tag_type = vendor_tag_descriptor_get_tag_type;
+    }
+    if((res = set_camera_metadata_vendor_ops(opsPtr)) != OK) {
+        ALOGE("%s: Could not set vendor tag descriptor, received error %s (%d)."
+                , __FUNCTION__, strerror(-res), res);
+    }
+    return res;
+}
+
+void VendorTagDescriptor::clearGlobalVendorTagDescriptor() {
+    Mutex::Autolock al(sLock);
+    set_camera_metadata_vendor_ops(NULL);
+    sGlobalVendorTagDescriptor.clear();
+}
+
+sp<VendorTagDescriptor> VendorTagDescriptor::getGlobalVendorTagDescriptor() {
+    Mutex::Autolock al(sLock);
+    return sGlobalVendorTagDescriptor;
+}
+
+extern "C" {
+
+int vendor_tag_descriptor_get_tag_count(const vendor_tag_ops_t* /*v*/) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptor == NULL) {
+        ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
+        return VENDOR_TAG_COUNT_ERR;
+    }
+    return sGlobalVendorTagDescriptor->getTagCount();
+}
+
+void vendor_tag_descriptor_get_all_tags(const vendor_tag_ops_t* /*v*/, uint32_t* tagArray) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptor == NULL) {
+        ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
+        return;
+    }
+    sGlobalVendorTagDescriptor->getTagArray(tagArray);
+}
+
+const char* vendor_tag_descriptor_get_section_name(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptor == NULL) {
+        ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
+        return VENDOR_SECTION_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptor->getSectionName(tag);
+}
+
+const char* vendor_tag_descriptor_get_tag_name(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptor == NULL) {
+        ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
+        return VENDOR_TAG_NAME_ERR;
+    }
+    return sGlobalVendorTagDescriptor->getTagName(tag);
+}
+
+int vendor_tag_descriptor_get_tag_type(const vendor_tag_ops_t* /*v*/, uint32_t tag) {
+    Mutex::Autolock al(sLock);
+    if (sGlobalVendorTagDescriptor == NULL) {
+        ALOGE("%s: Vendor tag descriptor not initialized.", __FUNCTION__);
+        return VENDOR_TAG_TYPE_ERR;
+    }
+    return sGlobalVendorTagDescriptor->getTagType(tag);
+}
+
+} /* extern "C" */
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
diff --git a/camera/common/1.0/default/include/CameraMetadata.h b/camera/common/1.0/default/include/CameraMetadata.h
new file mode 100644
index 0000000..d5e4d56
--- /dev/null
+++ b/camera/common/1.0/default/include/CameraMetadata.h
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ */
+
+#ifndef CAMERA_COMMON_1_0_CAMERAMETADATA_H
+#define CAMERA_COMMON_1_0_CAMERAMETADATA_H
+
+#include "system/camera_metadata.h"
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+class VendorTagDescriptor;
+
+/**
+ * A convenience wrapper around the C-based camera_metadata_t library.
+ */
+class CameraMetadata {
+  public:
+    /** Creates an empty object; best used when expecting to acquire contents
+     * from elsewhere */
+    CameraMetadata();
+    /** Creates an object with space for entryCapacity entries, with
+     * dataCapacity extra storage */
+    CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10);
+
+    ~CameraMetadata();
+
+    /** Takes ownership of passed-in buffer */
+    CameraMetadata(camera_metadata_t *buffer);
+    /** Clones the metadata */
+    CameraMetadata(const CameraMetadata &other);
+
+    /**
+     * Assignment clones metadata buffer.
+     */
+    CameraMetadata &operator=(const CameraMetadata &other);
+    CameraMetadata &operator=(const camera_metadata_t *buffer);
+
+    /**
+     * Get reference to the underlying metadata buffer. Ownership remains with
+     * the CameraMetadata object, but non-const CameraMetadata methods will not
+     * work until unlock() is called. Note that the lock has nothing to do with
+     * thread-safety, it simply prevents the camera_metadata_t pointer returned
+     * here from being accidentally invalidated by CameraMetadata operations.
+     */
+    const camera_metadata_t* getAndLock() const;
+
+    /**
+     * Unlock the CameraMetadata for use again. After this unlock, the pointer
+     * given from getAndLock() may no longer be used. The pointer passed out
+     * from getAndLock must be provided to guarantee that the right object is
+     * being unlocked.
+     */
+    status_t unlock(const camera_metadata_t *buffer) const;
+
+    /**
+     * Release a raw metadata buffer to the caller. After this call,
+     * CameraMetadata no longer references the buffer, and the caller takes
+     * responsibility for freeing the raw metadata buffer (using
+     * free_camera_metadata()), or for handing it to another CameraMetadata
+     * instance.
+     */
+    camera_metadata_t* release();
+
+    /**
+     * Clear the metadata buffer and free all storage used by it
+     */
+    void clear();
+
+    /**
+     * Acquire a raw metadata buffer from the caller. After this call,
+     * the caller no longer owns the raw buffer, and must not free or manipulate it.
+     * If CameraMetadata already contains metadata, it is freed.
+     */
+    void acquire(camera_metadata_t* buffer);
+
+    /**
+     * Acquires raw buffer from other CameraMetadata object. After the call, the argument
+     * object no longer has any metadata.
+     */
+    void acquire(CameraMetadata &other);
+
+    /**
+     * Append metadata from another CameraMetadata object.
+     */
+    status_t append(const CameraMetadata &other);
+
+    /**
+     * Append metadata from a raw camera_metadata buffer
+     */
+    status_t append(const camera_metadata* other);
+
+    /**
+     * Number of metadata entries.
+     */
+    size_t entryCount() const;
+
+    /**
+     * Is the buffer empty (no entires)
+     */
+    bool isEmpty() const;
+
+    /**
+     * Sort metadata buffer for faster find
+     */
+    status_t sort();
+
+    /**
+     * Update metadata entry. Will create entry if it doesn't exist already, and
+     * will reallocate the buffer if insufficient space exists. Overloaded for
+     * the various types of valid data.
+     */
+    status_t update(uint32_t tag,
+            const uint8_t *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const int32_t *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const float *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const int64_t *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const double *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const camera_metadata_rational_t *data, size_t data_count);
+    status_t update(uint32_t tag,
+            const String8 &string);
+    status_t update(const camera_metadata_ro_entry &entry);
+
+
+    template<typename T>
+    status_t update(uint32_t tag, Vector<T> data) {
+        return update(tag, data.array(), data.size());
+    }
+
+    /**
+     * Check if a metadata entry exists for a given tag id
+     *
+     */
+    bool exists(uint32_t tag) const;
+
+    /**
+     * Get metadata entry by tag id
+     */
+    camera_metadata_entry find(uint32_t tag);
+
+    /**
+     * Get metadata entry by tag id, with no editing
+     */
+    camera_metadata_ro_entry find(uint32_t tag) const;
+
+    /**
+     * Delete metadata entry by tag
+     */
+    status_t erase(uint32_t tag);
+
+    /**
+     * Swap the underlying camera metadata between this and the other
+     * metadata object.
+     */
+    void swap(CameraMetadata &other);
+
+    /**
+     * Dump contents into FD for debugging. The verbosity levels are
+     * 0: Tag entry information only, no data values
+     * 1: Level 0 plus at most 16 data values per entry
+     * 2: All information
+     *
+     * The indentation parameter sets the number of spaces to add to the start
+     * each line of output.
+     */
+    void dump(int fd, int verbosity = 1, int indentation = 0) const;
+
+    /**
+     * Find tag id for a given tag name, also checking vendor tags if available.
+     * On success, returns OK and writes the tag id into tag.
+     *
+     * This is a slow method.
+     */
+    static status_t getTagFromName(const char *name,
+            const VendorTagDescriptor* vTags, uint32_t *tag);
+
+  private:
+    camera_metadata_t *mBuffer;
+    mutable bool       mLocked;
+
+    /**
+     * Check if tag has a given type
+     */
+    status_t checkType(uint32_t tag, uint8_t expectedType);
+
+    /**
+     * Base update entry method
+     */
+    status_t updateImpl(uint32_t tag, const void *data, size_t data_count);
+
+    /**
+     * Resize metadata buffer if needed by reallocating it and copying it over.
+     */
+    status_t resizeIfNeeded(size_t extraEntries, size_t extraData);
+
+};
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
new file mode 100644
index 0000000..68d4f90
--- /dev/null
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef CAMERA_COMMON_1_0_CAMERAMODULE_H
+#define CAMERA_COMMON_1_0_CAMERAMODULE_H
+
+#include <hardware/camera.h>
+#include <utils/Mutex.h>
+#include <utils/KeyedVector.h>
+
+#include "CameraMetadata.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+/**
+ * A wrapper class for HAL camera module.
+ *
+ * This class wraps camera_module_t returned from HAL to provide a wrapped
+ * get_camera_info implementation which CameraService generates some
+ * camera characteristics keys defined in newer HAL version on an older HAL.
+ */
+class CameraModule : public RefBase {
+public:
+    explicit CameraModule(camera_module_t *module);
+    virtual ~CameraModule();
+
+    // Must be called after construction
+    // Returns OK on success, NO_INIT on failure
+    int init();
+
+    int getCameraInfo(int cameraId, struct camera_info *info);
+    int getDeviceVersion(int cameraId);
+    int getNumberOfCameras(void);
+    int open(const char* id, struct hw_device_t** device);
+    bool isOpenLegacyDefined() const;
+    int openLegacy(const char* id, uint32_t halVersion, struct hw_device_t** device);
+    int setCallbacks(const camera_module_callbacks_t *callbacks);
+    bool isVendorTagDefined() const;
+    void getVendorTagOps(vendor_tag_ops_t* ops);
+    bool isSetTorchModeSupported() const;
+    int setTorchMode(const char* camera_id, bool enable);
+    uint16_t getModuleApiVersion() const;
+    const char* getModuleName() const;
+    uint16_t getHalApiVersion() const;
+    const char* getModuleAuthor() const;
+    // Only used by CameraModuleFixture native test. Do NOT use elsewhere.
+    void *getDso();
+
+private:
+    // Derive camera characteristics keys defined after HAL device version
+    static void deriveCameraCharacteristicsKeys(uint32_t deviceVersion, CameraMetadata &chars);
+    // Helper function to append available[request|result|chars]Keys
+    static void appendAvailableKeys(CameraMetadata &chars,
+            int32_t keyTag, const Vector<int32_t>& appendKeys);
+    status_t filterOpenErrorCode(status_t err);
+    camera_module_t *mModule;
+    KeyedVector<int, camera_info> mCameraInfoMap;
+    KeyedVector<int, int> mDeviceVersionMap;
+    Mutex mCameraInfoLock;
+};
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif
diff --git a/camera/common/1.0/default/include/VendorTagDescriptor.h b/camera/common/1.0/default/include/VendorTagDescriptor.h
new file mode 100644
index 0000000..8d8ded9
--- /dev/null
+++ b/camera/common/1.0/default/include/VendorTagDescriptor.h
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+#ifndef CAMERA_COMMON_1_0_VENDORTAGDESCRIPTOR_H
+#define CAMERA_COMMON_1_0_VENDORTAGDESCRIPTOR_H
+
+#include <utils/Vector.h>
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+#include <utils/RefBase.h>
+#include <system/camera_vendor_tags.h>
+
+#include <stdint.h>
+
+namespace android {
+namespace hardware {
+namespace camera2 {
+namespace params {
+
+/**
+ * VendorTagDescriptor objects are containers for the vendor tag
+ * definitions provided, and are typically used to pass the vendor tag
+ * information enumerated by the HAL to clients of the camera service.
+ */
+class VendorTagDescriptor {
+    public:
+        virtual ~VendorTagDescriptor();
+
+        VendorTagDescriptor();
+        VendorTagDescriptor(const VendorTagDescriptor& src);
+        VendorTagDescriptor& operator=(const VendorTagDescriptor& rhs);
+
+        void copyFrom(const VendorTagDescriptor& src);
+
+        /**
+         * The following 'get*' methods implement the corresponding
+         * functions defined in
+         * system/media/camera/include/system/camera_vendor_tags.h
+         */
+
+        // Returns the number of vendor tags defined.
+        int getTagCount() const;
+
+        // Returns an array containing the id's of vendor tags defined.
+        void getTagArray(uint32_t* tagArray) const;
+
+        // Returns the section name string for a given vendor tag id.
+        const char* getSectionName(uint32_t tag) const;
+
+        // Returns the index in section vectors returned in getAllSectionNames()
+        // for a given vendor tag id. -1 if input tag does not exist.
+        ssize_t getSectionIndex(uint32_t tag) const;
+
+        // Returns the tag name string for a given vendor tag id.
+        const char* getTagName(uint32_t tag) const;
+
+        // Returns the tag type for a given vendor tag id.
+        int getTagType(uint32_t tag) const;
+
+        /**
+         * Convenience method to get a vector containing all vendor tag
+         * sections, or an empty vector if none are defined.
+         * The pointer is valid for the lifetime of the VendorTagDescriptor,
+         * or until copyFrom is invoked.
+         */
+        const SortedVector<String8>* getAllSectionNames() const;
+
+        /**
+         * Lookup the tag id for a given tag name and section.
+         *
+         * Returns OK on success, or a negative error code.
+         */
+        status_t lookupTag(const String8& name, const String8& section, /*out*/uint32_t* tag) const;
+
+        /**
+         * Dump the currently configured vendor tags to a file descriptor.
+         */
+        void dump(int fd, int verbosity, int indentation) const;
+
+    protected:
+        KeyedVector<String8, KeyedVector<String8, uint32_t>*> mReverseMapping;
+        KeyedVector<uint32_t, String8> mTagToNameMap;
+        KeyedVector<uint32_t, uint32_t> mTagToSectionMap; // Value is offset in mSections
+        KeyedVector<uint32_t, int32_t> mTagToTypeMap;
+        SortedVector<String8> mSections;
+        // must be int32_t to be compatible with Parcel::writeInt32
+        int32_t mTagCount;
+
+        vendor_tag_ops mVendorOps;
+};
+} /* namespace params */
+} /* namespace camera2 */
+
+namespace camera {
+namespace common {
+namespace V1_0 {
+namespace helper {
+
+/**
+ * This version of VendorTagDescriptor must be stored in Android sp<>, and adds support for using it
+ * as a global tag descriptor.
+ *
+ * It's a child class of the basic hardware::camera2::params::VendorTagDescriptor since basic
+ * Parcelable objects cannot require being kept in an sp<> and still work with auto-generated AIDL
+ * interface implementations.
+ */
+class VendorTagDescriptor :
+            public ::android::hardware::camera2::params::VendorTagDescriptor,
+            public LightRefBase<VendorTagDescriptor> {
+
+  public:
+
+    /**
+     * Create a VendorTagDescriptor object from the given vendor_tag_ops_t
+     * struct.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t createDescriptorFromOps(const vendor_tag_ops_t* vOps,
+            /*out*/
+            sp<VendorTagDescriptor>& descriptor);
+
+    /**
+     * Sets the global vendor tag descriptor to use for this process.
+     * Camera metadata operations that access vendor tags will use the
+     * vendor tag definitions set this way.
+     *
+     * Returns OK on success, or a negative error code.
+     */
+    static status_t setAsGlobalVendorTagDescriptor(const sp<VendorTagDescriptor>& desc);
+
+    /**
+     * Returns the global vendor tag descriptor used by this process.
+     * This will contain NULL if no vendor tags are defined.
+     */
+    static sp<VendorTagDescriptor> getGlobalVendorTagDescriptor();
+
+    /**
+     * Clears the global vendor tag descriptor used by this process.
+     */
+    static void clearGlobalVendorTagDescriptor();
+
+};
+
+} // namespace helper
+} // namespace V1_0
+} // namespace common
+} // namespace camera
+} // namespace hardware
+} // namespace android
+
+#endif /* CAMERA_COMMON_1_0_VENDORTAGDESCRIPTOR_H */
diff --git a/camera/common/1.0/types.hal b/camera/common/1.0/types.hal
new file mode 100644
index 0000000..0393107
--- /dev/null
+++ b/camera/common/1.0/types.hal
@@ -0,0 +1,413 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.common@1.0;
+
+/**
+ * Common enumeration and structure definitions for all HALs under
+ * android.hardware.camera
+ */
+
+/**
+ * Status codes for camera HAL method calls.
+ *
+ */
+enum Status : uint32_t {
+    /**
+     * Method call succeeded
+     */
+    OK = 0,
+
+    /**
+     * One of the arguments to the method call is invalid. For example,
+     * the camera ID is unknown.
+     */
+    ILLEGAL_ARGUMENT = 1,
+
+    /**
+     * The specified camera device is already in use
+     */
+    CAMERA_IN_USE = 2,
+
+    /**
+     * The HAL cannot support more simultaneous cameras in use.
+     */
+    MAX_CAMERAS_IN_USE = 3,
+
+    /**
+     * This HAL does not support this method.
+     */
+    METHOD_NOT_SUPPORTED = 4,
+
+    /**
+     * The specified camera device does not support this operation.
+     */
+    OPERATION_NOT_SUPPORTED = 5,
+
+    /**
+     * This camera device is no longer connected or otherwise available for use
+     */
+    CAMERA_DISCONNECTED = 6,
+
+    /**
+     * The HAL has encountered an internal error and cannot complete the
+     * request.
+     */
+    INTERNAL_ERROR = 7
+};
+
+/**
+ * Possible states that the flash unit on a closed camera device can be set to
+ * via the ICameraProvider::setTorchMode() method.
+ */
+enum TorchMode : uint32_t {
+    OFF = 0, // Turn off the flash
+    ON  = 1  // Turn on the flash to torch mode
+};
+
+/**
+ * Camera metadata type - duplicated from VNDK libcamera_metadata for vendor tag
+ * definitions.
+ */
+enum CameraMetadataType : uint32_t {
+    // Unsigned 8-bit integer (uint8_t)
+    BYTE = 0,
+    // Signed 32-bit integer (int32_t)
+    INT32 = 1,
+    // 32-bit float (float)
+    FLOAT = 2,
+    // Signed 64-bit integer (int64_t)
+    INT64 = 3,
+    // 64-bit float (double)
+    DOUBLE = 4,
+    // A 64-bit fraction (camera_metadata_rational_t)
+    RATIONAL = 5
+};
+
+/**
+ * A single vendor-unique metadata tag.
+ * The full name of the tag is <sectionName>.<tagName>
+ */
+struct VendorTag {
+    uint32_t tagId; // Tag identifier, must be >= TagBoundaryId::VENDOR
+    string tagName; // Name of tag, not including section name
+    CameraMetadataType tagType;
+};
+
+/**
+ * A set of related vendor tags.
+ */
+struct VendorTagSection {
+    string sectionName; // Section name; must be namespaced within vendor's name
+    vec<VendorTag> tags; // List of tags in this section
+};
+
+enum TagBoundaryId : uint32_t {
+    AOSP    = 0x0,         // First valid tag id for android-defined tags
+    VENDOR  = 0x80000000u  // First valid tag id for vendor extension tags
+};
+
+/**
+ * CameraDeviceStatus
+ *
+ * The current status of a camera device, as sent by a camera provider HAL
+ * through the ICameraProviderCallback::cameraDeviceStatusChange() call.
+ *
+ * At startup, the camera service must assume all internal camera devices listed
+ * by ICameraProvider::getCameraIdList() are in the PRESENT state. The provider
+ * must invoke ICameraProviderCallback::cameraDeviceStatusChange to inform the
+ * service of any initially NOT_PRESENT internal devices, and of any PRESENT
+ * external camera devices, as soon as the camera service has called
+ * ICameraProvider::setCallback().
+ *
+ * Allowed state transitions:
+ *      PRESENT            -> NOT_PRESENT
+ *      NOT_PRESENT        -> ENUMERATING
+ *      NOT_PRESENT        -> PRESENT
+ *      ENUMERATING        -> PRESENT
+ *      ENUMERATING        -> NOT_PRESENT
+ */
+enum CameraDeviceStatus : uint32_t {
+    /**
+     * The camera device is not currently connected, and trying to reference it
+     * in provider method calls must return status code ILLEGAL_ARGUMENT.
+     *
+     */
+    NOT_PRESENT = 0,
+
+    /**
+     * The camera device is connected, and opening it is possible, as long as
+     * sufficient resources are available.
+     *
+     * By default, the framework must assume all devices returned by
+     * ICameraProvider::getCameraIdList() are in this state.
+     */
+    PRESENT = 1,
+
+    /**
+     * The camera device is connected, but it is undergoing enumeration and
+     * startup, and so opening the device must return CAMERA_IN_USE.
+     *
+     * Attempting to call ICameraProvider::getCameraCharacteristics() must
+     * succeed, however.
+     */
+    ENUMERATING = 2,
+
+};
+
+/**
+ * TorchModeStatus:
+ *
+ * The current status of the torch mode on a given camera device, sent by a
+ * camera provider HAL via the ICameraProviderCallback::TorchModeStatusChange()
+ * call.
+ *
+ * The torch mode status of a camera device is applicable only when the camera
+ * device is present. The camera service must not call
+ * ICameraProvider::setTorchMode() to turn on torch mode of a camera device if
+ * the camera device is not present. At camera service startup time, the
+ * framework must assume torch modes are in the AVAILABLE_OFF state if the
+ * camera device is present and the camera characteristics entry
+ * android.flash.info.available is reported as true via
+ * ICameraProvider::getCameraCharacteristics() call. The same is assumed for
+ * external camera devices when they are initially connected.
+ *
+ * The camera service requires the following behaviors from the camera provider
+ * HAL when a camera device's status changes:
+ *
+ *  1. A previously-disconnected camera device becomes connected. After
+ *      ICameraProviderCallback::CameraDeviceStatusChange() is invoked to inform
+ *      the camera service that the camera device is present, the framework must
+ *      assume the camera device's torch mode is in AVAILABLE_OFF state if it
+ *      has a flash unit. The camera provider HAL does not need to invoke
+ *      ICameraProviderCallback::TorchModeStatusChange() unless the flash unit
+ *      is unavailable to use by ICameraProvider::setTorchMode().
+ *
+ *  2. A previously-connected camera becomes disconnected. After
+ *      ICameraProviderCallback::CameraDeviceStatusChange() is invoked to inform
+ *      the camera service that the camera device is not present, the framework
+ *      must not call ICameraProvider::setTorchMode() for the disconnected camera
+ *      device until it is connected again. The camera provider HAL does not
+ *      need to invoke ICameraProviderCallback::TorchModeStatusChange()
+ *      separately to inform that the flash unit has become NOT_AVAILABLE.
+ *
+ *  3. openCameraDevice() or openCameraDeviceVersion() is called to open a
+ *      camera device. The camera provider HAL must invoke
+ *      ICameraProviderCallback::TorchModeStatusChange() for all flash units
+ *      that have entered NOT_AVAILABLE state and can not be turned on by
+ *      calling ICameraProvider::setTorchMode() due to this open() call.
+ *      openCameraDevice() must not trigger AVAILABLE_OFF before NOT_AVAILABLE
+ *      for all flash units that have become unavailable.
+ *
+ *  4. ICameraDevice.close() is called to close a camera device. The camera
+ *      provider HAL must call ICameraProviderCallback::torchModeStatusChange()
+ *      for all flash units that have now entered the AVAILABLE_OFF state and
+ *      can be turned on by calling ICameraProvider::setTorchMode() again because
+ *      of sufficient new camera resources being freed up by this close() call.
+ *
+ *  Note that the camera service calling ICameraProvider::setTorchMode()
+ *  successfully must trigger AVAILABLE_OFF or AVAILABLE_ON callback for the
+ *  given camera device. Additionally it must trigger AVAILABLE_OFF callbacks
+ *  for other previously-on torch modes if HAL cannot keep multiple devices'
+ *  flashlights on simultaneously.
+ */
+enum TorchModeStatus : uint32_t {
+    /**
+     * The flash unit is no longer available and the torch mode can not be
+     * turned on by calling setTorchMode(). If the torch mode was AVAILABLE_ON,
+     * the flashlight must be turned off by the provider HAL before the provider
+     * HAL calls torchModeStatusChange().
+     */
+    NOT_AVAILABLE = 0,
+
+    /**
+     * A torch mode has become off and is available to be turned on via
+     * ICameraProvider::setTorchMode(). This may happen in the following
+     * cases:
+     *   1. After the resources to turn on the torch mode have become available.
+     *   2. After ICameraProvider::setTorchMode() is called to turn off the torch
+     *      mode.
+     *   3. After the camera service turned on the torch mode for some other
+     *      camera device and the provider HAL had to turn off the torch modes
+     *      of other camera device(s) that were previously on, due to lack of
+     *      resources to keep them all on.
+     */
+    AVAILABLE_OFF = 1,
+
+    /**
+     * A torch mode has become on and is available to be turned off via
+     * ICameraProvider::setTorchMode(). This can happen only after
+     * ICameraProvider::setTorchMode() has been called to turn on the torch mode.
+     */
+    AVAILABLE_ON = 2,
+
+};
+
+/**
+ * CameraResourceCost:
+ *
+ * Structure defining the abstract resource cost of opening a camera device,
+ * and any usage conflicts between multiple camera devices.
+ *
+ * Obtainable via ICameraDevice::getResourceCost()
+ */
+struct CameraResourceCost {
+    /**
+     * The total resource "cost" of using this camera, represented as an integer
+     * value in the range [0, 100] where 100 represents total usage of the
+     * shared resource that is the limiting bottleneck of the camera subsystem.
+     * This may be a very rough estimate, and is used as a hint to the camera
+     * service to determine when to disallow multiple applications from
+     * simultaneously opening different cameras advertised by the camera
+     * service.
+     *
+     * The camera service must be able to simultaneously open and use any
+     * combination of camera devices exposed by the HAL where the sum of
+     * the resource costs of these cameras is <= 100. For determining cost,
+     * each camera device must be assumed to be configured and operating at
+     * the maximally resource-consuming framerate and stream size settings
+     * available in the configuration settings exposed for that device through
+     * the camera metadata.
+     *
+     * The camera service may still attempt to simultaneously open combinations
+     * of camera devices with a total resource cost > 100. This may succeed or
+     * fail. If this succeeds, combinations of configurations that are not
+     * supported due to resource constraints from having multiple open devices
+     * must fail during the configure calls. If the total resource cost is <=
+     * 100, open and configure must never fail for any stream configuration
+     * settings or other device capabilities that would normally succeed for a
+     * device when it is the only open camera device.
+     *
+     * This field may be used to determine whether background applications are
+     * allowed to use this camera device while other applications are using
+     * other camera devices. Note: multiple applications must never be allowed
+     * by the camera service to simultaneously open the same camera device.
+     *
+     * Example use cases:
+     *
+     * Ex. 1: Camera Device 0 = Back Camera
+     *        Camera Device 1 = Front Camera
+     *   - Using both camera devices causes a large framerate slowdown due to
+     *     limited ISP bandwidth.
+     *
+     *   Configuration:
+     *
+     *   Camera Device 0 - resourceCost = 51
+     *                     conflicting_devices = empty
+     *   Camera Device 1 - resourceCost = 51
+     *                     conflicting_devices = empty
+     *
+     *   Result:
+     *
+     *   Since the sum of the resource costs is > 100, if a higher-priority
+     *   application has either device open, no lower-priority applications must
+     *   be allowed by the camera service to open either device. If a
+     *   lower-priority application is using a device that a higher-priority
+     *   subsequently attempts to open, the lower-priority application must be
+     *   forced to disconnect the the device.
+     *
+     *   If the highest-priority application chooses, it may still attempt to
+     *   open both devices (since these devices are not listed as conflicting in
+     *   the conflicting_devices fields), but usage of these devices may fail in
+     *   the open or configure calls.
+     *
+     * Ex. 2: Camera Device 0 = Left Back Camera
+     *        Camera Device 1 = Right Back Camera
+     *        Camera Device 2 = Combined stereo camera using both right and left
+     *                          back camera sensors used by devices 0, and 1
+     *        Camera Device 3 = Front Camera
+     *   - Due to do hardware constraints, up to two cameras may be open at
+     *     once. The combined stereo camera may never be used at the same time
+     *     as either of the two back camera devices (device 0, 1), and typically
+     *     requires too much bandwidth to use at the same time as the front
+     *     camera (device 3).
+     *
+     *   Configuration:
+     *
+     *   Camera Device 0 - resourceCost = 50
+     *                     conflicting_devices = { 2 }
+     *   Camera Device 1 - resourceCost = 50
+     *                     conflicting_devices = { 2 }
+     *   Camera Device 2 - resourceCost = 100
+     *                     conflicting_devices = { 0, 1 }
+     *   Camera Device 3 - resourceCost = 50
+     *                     conflicting_devices = empty
+     *
+     *   Result:
+     *
+     *   Based on the conflicting_devices fields, the camera service guarantees
+     *   that the following sets of open devices must never be allowed: { 1, 2
+     *   }, { 0, 2 }.
+     *
+     *   Based on the resourceCost fields, if a high-priority foreground
+     *   application is using camera device 0, a background application would be
+     *   allowed to open camera device 1 or 3 (but would be forced to disconnect
+     *   it again if the foreground application opened another device).
+     *
+     *   The highest priority application may still attempt to simultaneously
+     *   open devices 0, 2, and 3, but the HAL may fail in open or configure
+     *   calls for this combination.
+     *
+     * Ex. 3: Camera Device 0 = Back Camera
+     *        Camera Device 1 = Front Camera
+     *        Camera Device 2 = Low-power Front Camera that uses the same sensor
+     *                          as device 1, but only exposes image stream
+     *                          resolutions that can be used in low-power mode
+     *  - Using both front cameras (device 1, 2) at the same time is impossible
+     *    due a shared physical sensor. Using the back and "high-power" front
+     *    camera (device 1) may be impossible for some stream configurations due
+     *    to hardware limitations, but the "low-power" front camera option may
+     *    always be used as it has special dedicated hardware.
+     *
+     *   Configuration:
+     *
+     *   Camera Device 0 - resourceCost = 100
+     *                     conflicting_devices = empty
+     *   Camera Device 1 - resourceCost = 100
+     *                     conflicting_devices = { 2 }
+     *   Camera Device 2 - resourceCost = 0
+     *                     conflicting_devices = { 1 }
+     *   Result:
+     *
+     *   Based on the conflicting_devices fields, the camera service guarantees
+     *   that the following sets of open devices must never be allowed:
+     *   { 1, 2 }.
+     *
+     *   Based on the resourceCost fields, only the highest priority application
+     *   may attempt to open both device 0 and 1 at the same time. If a
+     *   higher-priority application is not using device 1 or 2, a low-priority
+     *   background application may open device 2 (but must be forced to
+     *   disconnect it if a higher-priority application subsequently opens
+     *   device 1 or 2).
+     */
+    uint32_t resourceCost;
+
+    /**
+     * An array of camera device IDs indicating other devices that cannot be
+     * simultaneously opened while this camera device is in use.
+     *
+     * This field is intended to be used to indicate that this camera device
+     * is a composite of several other camera devices, or otherwise has
+     * hardware dependencies that prohibit simultaneous usage. If there are no
+     * dependencies, an empty list may be returned to indicate this.
+     *
+     * The camera service must never simultaneously open any of the devices
+     * in this list while this camera device is open.
+     *
+     */
+    vec<string> conflictingDevices;
+
+};
diff --git a/camera/common/README.md b/camera/common/README.md
new file mode 100644
index 0000000..c177ad8
--- /dev/null
+++ b/camera/common/README.md
@@ -0,0 +1,21 @@
+## Camera common HAL definitions ##
+---
+
+## Overview: ##
+
+The camera.common namesapce is used by the Android camera HALs for common
+enumeration and structure definitions.
+
+This includes standard status codes returned by most camera HAL methods.
+
+More complete information about the Android camera HAL and subsystem can be found at
+[source.android.com](http://source.android.com/devices/camera/index.html).
+
+## Version history: ##
+
+## types.hal: ##
+
+### @1.0:
+
+Common enum and struct definitions for all camera HAL interfaces. Does not
+define any interfaces of its own.
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
new file mode 100644
index 0000000..9a6941a
--- /dev/null
+++ b/camera/device/1.0/Android.bp
@@ -0,0 +1,78 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.camera.device@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@1.0",
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+        "ICameraDevicePreviewCallback.hal",
+    ],
+    out: [
+        "android/hardware/camera/device/1.0/types.cpp",
+        "android/hardware/camera/device/1.0/CameraDeviceAll.cpp",
+        "android/hardware/camera/device/1.0/CameraDeviceCallbackAll.cpp",
+        "android/hardware/camera/device/1.0/CameraDevicePreviewCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@1.0",
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+        "ICameraDevicePreviewCallback.hal",
+    ],
+    out: [
+        "android/hardware/camera/device/1.0/types.h",
+        "android/hardware/camera/device/1.0/ICameraDevice.h",
+        "android/hardware/camera/device/1.0/IHwCameraDevice.h",
+        "android/hardware/camera/device/1.0/BnHwCameraDevice.h",
+        "android/hardware/camera/device/1.0/BpHwCameraDevice.h",
+        "android/hardware/camera/device/1.0/BsCameraDevice.h",
+        "android/hardware/camera/device/1.0/ICameraDeviceCallback.h",
+        "android/hardware/camera/device/1.0/IHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/1.0/BnHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/1.0/BpHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/1.0/BsCameraDeviceCallback.h",
+        "android/hardware/camera/device/1.0/ICameraDevicePreviewCallback.h",
+        "android/hardware/camera/device/1.0/IHwCameraDevicePreviewCallback.h",
+        "android/hardware/camera/device/1.0/BnHwCameraDevicePreviewCallback.h",
+        "android/hardware/camera/device/1.0/BpHwCameraDevicePreviewCallback.h",
+        "android/hardware/camera/device/1.0/BsCameraDevicePreviewCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.device@1.0",
+    generated_sources: ["android.hardware.camera.device@1.0_genc++"],
+    generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/camera/device/1.0/ICameraDevice.hal b/camera/device/1.0/ICameraDevice.hal
new file mode 100644
index 0000000..d232a67
--- /dev/null
+++ b/camera/device/1.0/ICameraDevice.hal
@@ -0,0 +1,389 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@1.0;
+
+import android.hardware.camera.common@1.0::types;
+import ICameraDeviceCallback;
+import ICameraDevicePreviewCallback;
+
+/**
+ * Camera device HAL, legacy version
+ *
+ * DEPRECATED. New devices are strongly recommended to use Camera HAL v3.2 or
+ * newer.
+ *
+ * Supports the android.hardware.Camera API, and the android.hardware.camera2
+ * API in LEGACY mode only.
+ *
+ * Will be removed in the Android P release.
+ */
+interface ICameraDevice {
+
+    /**
+     * Get camera device resource cost information.
+     *
+     * This method may be called at any time, including before open()
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On success.
+     *     INTERNAL_ERROR:
+     *         An unexpected internal camera HAL error occurred, and the
+     *         resource cost is not available.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     * @return resourceCost
+     *     The resources required to open this camera device, or unspecified
+     *     values if status is not OK.
+     */
+    getResourceCost() generates (Status status, CameraResourceCost resourceCost);
+
+    /**
+     * Get basic camera information.
+     *
+     * This method may be called at any time, including before open()
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On success.
+     *     INTERNAL_ERROR:
+     *         An unexpected internal camera HAL error occurred, and the
+     *         camera information is not available.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     * @return info Basic information about this camera device, or unspecified
+     *     values if status is not OK.
+     */
+    getCameraInfo() generates (Status status, CameraInfo info);
+
+    /**
+     * setTorchMode:
+     *
+     * Turn on or off the torch mode of the flash unit associated with a given
+     * camera ID. If the operation is successful, HAL must notify the framework
+     * torch state by invoking
+     * ICameraProviderCallback::torchModeStatusChange() with the new state.
+     *
+     * The camera device has a higher priority accessing the flash unit. When
+     * there are any resource conflicts, such as when open() is called to fully
+     * activate a camera device, the provider must notify the framework through
+     * ICameraProviderCallback::torchModeStatusChange() that the torch mode has
+     * been turned off and the torch mode state has become
+     * TORCH_MODE_STATUS_NOT_AVAILABLE. When resources to turn on torch mode
+     * become available again, the provider must notify the framework through
+     * ICameraProviderCallback::torchModeStatusChange() that the torch mode
+     * state has become TORCH_MODE_STATUS_AVAILABLE_OFF for set_torch_mode() to
+     * be called.
+     *
+     * When the framework calls setTorchMode() to turn on the torch mode of a
+     * flash unit, if HAL cannot keep multiple torch modes on simultaneously,
+     * HAL must turn off the torch mode that was turned on by
+     * a previous setTorchMode() call and notify the framework that the torch
+     * mode state of that flash unit has become TORCH_MODE_STATUS_AVAILABLE_OFF.
+     *
+     * @param torchMode The new mode to set the device flash unit to.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful change to the torch state.
+     *     INTERNAL_ERROR:
+     *         The flash unit cannot be operated due to an unexpected internal
+     *         error.
+     *     ILLEGAL_ARGUMENT:
+     *         The camera ID is unknown.
+     *     CAMERA_IN_USE:
+     *         This camera device has been opened, so the torch cannot be
+     *         controlled until it is closed.
+     *     MAX_CAMERAS_IN_USE:
+     *         Due to other camera devices being open, or due to other
+     *         resource constraints, the torch cannot be controlled currently.
+     *     METHOD_NOT_SUPPORTED:
+     *         This provider does not support direct operation of flashlight
+     *         torch mode. The framework must open the camera device and turn
+     *         the torch on through the device interface.
+     *     OPERATION_NOT_SUPPORTED:
+     *         This camera device does not have a flash unit. This must
+     *         be returned if and only if android.flash.info.available is
+     *         false.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     *
+     */
+    setTorchMode(TorchMode mode) generates (Status status);
+
+    /**
+     * Dump state of the camera hardware.
+     *
+     * This must be callable at any time, whether the device is open or not.
+     *
+     * @param fd A native handle with one valid file descriptor. The descriptor
+     *     must be able to be used with dprintf() or equivalent to dump the
+     *     state of this camera device into the camera service dumpsys output.
+     *
+     * @return status The status code for this operation.
+     */
+    dumpState(handle fd) generates (Status status);
+
+    /**
+     * Open the camera device for active use.
+     *
+     * All methods besides getResourceCost(), getCameraInfo(), setTorchMode(),
+     * and dump() must not be called unless open() has been called successfully,
+     * and close() has not yet been called.
+     *
+     * @param callback Interface to invoke by the HAL for device callbacks.
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful open of the camera device.
+     *     INTERNAL_ERROR:
+     *         The camera device cannot be opened due to an internal
+     *         error.
+     *     ILLEGAL_ARGUMENT:
+     *         The callback handle is invalid (for example, it is null).
+     *     CAMERA_IN_USE:
+     *         This camera device is already open.
+     *     MAX_CAMERAS_IN_USE:
+     *         The maximal number of camera devices that can be
+     *         opened concurrently were opened already.
+     *     CAMERA_DISCONNECTED:
+     *         This external camera device has been disconnected, and is no
+     *         longer available. This interface is now stale, and a new instance
+     *         must be acquired if the device is reconnected. All subsequent
+     *         calls on this interface must return CAMERA_DISCONNECTED.
+     */
+    open(ICameraDeviceCallback callback) generates (Status status);
+
+
+    /*****
+     * All methods below this point must only be called between a successful
+     * open() call and a close() call.
+     */
+
+    /** Set the callback interface through which preview frames are sent */
+    setPreviewWindow(ICameraDevicePreviewCallback window)
+            generates (Status status);
+
+    /**
+     * Enable a message, or set of messages.
+     *
+     * @param msgType The bitfield of messages to enable.
+     */
+    enableMsgType(FrameCallbackFlags msgType);
+
+    /**
+     * Disable a message, or a set of messages.
+     *
+     * Once received a call to disableMsgType(CAMERA_MSG_VIDEO_FRAME), camera
+     * HAL must not rely on its client to call releaseRecordingFrame() to
+     * release video recording frames sent out by the cameral HAL before and
+     * after the disableMsgType(CAMERA_MSG_VIDEO_FRAME) call. Camera HAL
+     * clients must not modify/access any video recording frame after calling
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME).
+     *
+     * @param msgType The bitfield of messages to disable.
+     */
+    disableMsgType(FrameCallbackFlags msgType);
+
+    /**
+     * Query whether a message, or a set of messages, is enabled. Note that
+     * this is operates as an AND, if any of the messages queried are off, this
+     * must return false.
+     *
+     * @param msgType The bitfield of messages to query.
+     * @return enabled Whether all the specified flags are enabled.
+     */
+    msgTypeEnabled(FrameCallbackFlags msgType) generates (bool enabled);
+
+    /**
+     * Start preview mode.
+     *
+     * @return status The status code for this operation.
+     */
+    startPreview() generates (Status status);
+
+    /**
+     * Stop a previously started preview.
+     */
+    stopPreview();
+
+    /**
+     * Returns true if preview is enabled.
+     *
+     * @return enabled Whether preview is currently enabled.
+     */
+    previewEnabled() generates (bool enabled);
+
+    /**
+     * Request the camera HAL to store meta data or real YUV data in the video
+     * buffers sent out via CAMERA_MSG_VIDEO_FRAME for a recording session. If
+     * it is not called, the default camera HAL behavior is to store real YUV
+     * data in the video buffers.
+     *
+     * This method must be called before startRecording() in order to be
+     * effective.
+     *
+     * If meta data is stored in the video buffers, it is up to the receiver of
+     * the video buffers to interpret the contents and to find the actual frame
+     * data with the help of the meta data in the buffer. How this is done is
+     * outside of the scope of this method.
+     *
+     * Some camera HALs may not support storing meta data in the video buffers,
+     * but all camera HALs must support storing real YUV data in the video
+     * buffers. If the camera HAL does not support storing the meta data in the
+     * video buffers when it is requested to do do, INVALID_OPERATION must be
+     * returned. It is very useful for the camera HAL to pass meta data rather
+     * than the actual frame data directly to the video encoder, since the
+     * amount of the uncompressed frame data can be very large if video size is
+     * large.
+     *
+     * @param enable Set to true to instruct the camera HAL to store meta data
+     *     in the video buffers; false to instruct the camera HAL to store real
+     *     YUV data in the video buffers.
+     *
+     * @return status OK on success.
+     */
+    storeMetaDataInBuffers(bool enable) generates (Status status);
+
+    /**
+     * Start record mode.
+     *
+     * When a record image is available, a CAMERA_MSG_VIDEO_FRAME message is
+     * sent with the corresponding frame. Every record frame must be released by
+     * a camera HAL client via releaseRecordingFrame() before the client calls
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME). After the client calls
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+     * responsibility to manage the life-cycle of the video recording frames,
+     * and the client must not modify/access any video recording frames.
+     *
+     * @return status The status code for the operation.
+     */
+    startRecording() generates (Status status);
+
+    /**
+     * Stop a previously started recording.
+     */
+    stopRecording();
+
+    /**
+     * Returns true if recording is enabled.
+     *
+     * @return enabled True if recording is currently active.
+     */
+    recordingEnabled() generates (bool enabled);
+
+    /**
+     * Release a record frame previously returned by CAMERA_MSG_VIDEO_FRAME.
+     *
+     * It is camera HAL client's responsibility to release video recording
+     * frames sent out by the camera HAL before the camera HAL receives a call
+     * to disableMsgType(CAMERA_MSG_VIDEO_FRAME). After it receives the call to
+     * disableMsgType(CAMERA_MSG_VIDEO_FRAME), it is the camera HAL's
+     * responsibility to manage the life-cycle of the video recording frames.
+     *
+     * @param data The memory buffer to release a recording frame from.
+     * @param bufferIndex The specific buffer index to return to the HAL.
+     */
+    releaseRecordingFrame(MemoryId data, uint32_t bufferIndex);
+
+    /**
+     * Start auto focus.
+     *
+     * The notification callback routine is called with
+     * CAMERA_MSG_FOCUS once when focusing is complete. autoFocus() can be
+     * called again after that if another auto focus is needed.
+     *
+     * @return status The status code for this operation.
+     */
+    autoFocus() generates (Status status);
+
+    /**
+     * Cancels auto-focus function.
+     *
+     * If the auto-focus is still in progress, this function must cancel
+     * it. Whether the auto-focus is in progress or not, this function must
+     * return the focus position to the default. If the camera does not support
+     * auto-focus, this is a no-op.
+     *
+     * @return status The status code for this operation.
+     */
+    cancelAutoFocus() generates (Status status);
+
+    /**
+     * Take a picture.
+     *
+     * @return status The status code for this operation.
+     */
+    takePicture() generates (Status status);
+
+    /**
+     * Cancel a picture that was started with takePicture. Calling this method
+     * when no picture is being taken is a no-op.
+     *
+     * @return status The status code for this operation.
+     */
+    cancelPicture() generates (Status status);
+
+    /**
+     * Set the camera parameters.
+     *
+     * @param parms The parameter string, consisting of
+     *    '<key1>=<value1>; ...;<keyN>=<valueN>'.
+     * @return status The status code for this operation:
+     *     OK: Parameter update was successful
+     *     ILLEGAL_ARGUMENT: At least one parameter was invalid or not supported
+     *
+     */
+    setParameters(string parms) generates (Status status);
+
+    /**
+     * Retrieve the camera parameters.
+     */
+    getParameters() generates (string parms);
+
+    /**
+     * Send command to camera driver.
+     * The meaning of the arguments is defined by the value of cmd, documented
+     * in the CommandType definition.
+     *
+     * @param cmd The command to invoke.
+     * @param arg1 The first argument for the command, if needed.
+     * @param arg2 The second argument for the command, if needed.
+     *
+     * @return status The status code for this operation.
+     */
+    sendCommand(CommandType cmd, int32_t arg1, int32_t arg2)
+            generates (Status status);
+
+    /**
+     * Release the hardware resources owned by this object, shutting down the
+     * camera device.
+     */
+    close();
+
+};
diff --git a/camera/device/1.0/ICameraDeviceCallback.hal b/camera/device/1.0/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..97014ee
--- /dev/null
+++ b/camera/device/1.0/ICameraDeviceCallback.hal
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@1.0;
+
+interface ICameraDeviceCallback {
+
+    /**
+     * Notify the camera service of a particular event occurring
+     * The meaning of each parameter is defined by the value of msgType, and
+     * documented in the definition of NotifyCallbackMsg.
+     *
+     * @param msgType The type of the event.
+     * @param ext1 The first parameter for the event, if needed.
+     * @param ext2 The second parameter for the event, if needed.
+     */
+    notifyCallback(NotifyCallbackMsg msgType, int32_t ext1, int32_t ext2);
+
+    /**
+     * Define a memory buffer from the provided handle and size, and return a
+     * unique identifier for the HAL to use to reference it with.
+     *
+     * TODO(b/33269977): Ensure this aligns with design and performance goals.
+     *
+     * @param descriptor A native handle that must have exactly one file
+     *     descriptor in it; the file descriptor must be memory mappable to
+     *     bufferSize * bufferCount bytes.
+     * @param bufferSize The number of bytes a single buffer consists of.
+     * @param bufferCount The number of contiguous buffers that the descriptor
+     *     contains.
+     *
+     * @return memId A integer identifier for this memory buffer, for use with
+     *     data callbacks and unregistering memory.
+     */
+    registerMemory(handle descriptor, uint32_t bufferSize, uint32_t bufferCount)
+            generates (MemoryId memId);
+
+    /**
+     * Unregister a previously registered memory buffer
+     */
+    unregisterMemory(MemoryId memId);
+
+    /**
+     * Send a buffer of image data to the camera service
+     *
+     * @param msgType The kind of image buffer data this call represents.
+     * @param data A memory handle to the buffer containing the data.
+     * @param bufferIndex The offset into the memory handle where the buffer
+     *     starts.
+     *
+     */
+    dataCallback(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex);
+
+    /**
+     * Send a buffer of image data to the camera service, with a timestamp
+     *
+     * @param msgType The kind of image buffer data this call represents.
+     * @param data A memory handle to the buffer containing the data.
+     * @param bufferIndex The offset into the memory handle where the buffer
+     *     starts.
+     * @param timestamp The time this buffer was captured by the camera, in
+     *     nanoseconds.
+     *
+     */
+    dataCallbackTimestamp(DataCallbackMsg msgType, MemoryId data, uint32_t bufferIndex,
+            int64_t timestamp);
+
+};
diff --git a/camera/device/1.0/ICameraDevicePreviewCallback.hal b/camera/device/1.0/ICameraDevicePreviewCallback.hal
new file mode 100644
index 0000000..ebc7460
--- /dev/null
+++ b/camera/device/1.0/ICameraDevicePreviewCallback.hal
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@1.0;
+
+import android.hardware.camera.common@1.0::types;
+import android.hardware.graphics.allocator@2.0::types;
+import android.hardware.graphics.common@1.0::types;
+
+/**
+ * Camera device HAL@1.0 preview stream operation interface.
+ */
+interface ICameraDevicePreviewCallback {
+
+    /**
+     * Acquire a buffer to write a preview buffer into.
+     *
+     * @return status The status code for this operation. If not OK, then
+     *     buffer and stride must not be used.
+     * @return buffer A handle to the buffer to write into.
+     * @return stride The stride between two rows of pixels in this buffer.
+     */
+    dequeueBuffer() generates (Status status, handle buffer, uint32_t stride);
+
+    /**
+     * Send a filled preview buffer to its consumer.
+     *
+     * @param buffer The handle to the preview buffer that's been filled.
+     * @return status The status code for this operation.
+     */
+    enqueueBuffer(handle buffer) generates (Status status);
+
+    /**
+     * Return a preview buffer unfilled. This buffer must not be sent on to the
+     * preview consumer as a valid buffer, but may be reused as if it were
+     * empty.
+     *
+     * @param buffer The handle to the preview buffer to return.
+     * @return status The status code for this operation.
+     */
+    cancelBuffer(handle buffer) generates (Status status);
+
+    /**
+     * Set the number of preview buffers needed by the HAL.
+     *
+     * @param count The maximum number of preview buffers to allocate.
+     * @return status The status code for this operation.
+     */
+    setBufferCount(uint32_t count) generates (Status status);
+
+    /**
+     * Set the dimensions and format of future preview buffers.
+     *
+     * The next buffer that is dequeued must match the requested size and
+     * format.
+     *
+     * @return Status The status code for this operation.
+     */
+    setBuffersGeometry(uint32_t w, uint32_t h,
+            android.hardware.graphics.common@1.0::PixelFormat format)
+            generates (Status status);
+
+    /**
+     * Set the valid region of image data for the next buffer(s) to be enqueued.
+     *
+     * @return Status The status code for this operation.
+     */
+    setCrop(int32_t left, int32_t top, int32_t right, int32_t bottom)
+            generates (Status status);
+
+    /**
+     * Set the producer usage flags for the next buffer(s) to be enqueued.
+     *
+     * @return Status The status code for this operation.
+     */
+    setUsage(ProducerUsage usage) generates (Status status);
+
+    /**
+     * Set the expected buffering mode for the preview output.
+     */
+    setSwapInterval(int32_t interval) generates (Status status);
+
+    /**
+     * Get the minimum number of buffers the preview consumer endpoint needs
+     * to hold for correct operation.
+     *
+     * @return Status The status code for this operation.
+     * @return count The number of buffers the consumer has requested.
+     */
+    getMinUndequeuedBufferCount() generates (Status status, uint32_t count);
+
+    /**
+     * Set the timestamp for the next buffer to enqueue
+     *
+     * Timestamps are measured in nanoseconds, and must be comparable
+     * and monotonically increasing between two frames in the same
+     * preview stream. They do not need to be comparable between
+     * consecutive or parallel preview streams, cameras, or app runs.
+     *
+     * @param timestamp The timestamp to set for future buffers.
+     * @return Status The status code for this operation.
+     */
+    setTimestamp(int64_t timestamp) generates (Status status);
+
+};
diff --git a/camera/device/1.0/types.hal b/camera/device/1.0/types.hal
new file mode 100644
index 0000000..83c0be4
--- /dev/null
+++ b/camera/device/1.0/types.hal
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@1.0;
+
+enum CameraFacing : uint32_t {
+    /** The facing of the camera is opposite to that of the screen. */
+    BACK = 0,
+    /** The facing of the camera is the same as that of the screen. */
+    FRONT = 1,
+    /**
+     * The facing of the camera is not fixed relative to the screen.
+     * The cameras with this facing are external cameras, e.g. USB cameras.
+     */
+    EXTERNAL = 2
+};
+
+/**
+ * Basic information about a camera device, always accessible via
+ * ICameraDevice::getCameraInfo().
+ */
+struct CameraInfo {
+    /**
+     * The direction that this device faces.
+     */
+    CameraFacing facing;
+
+    /**
+     * The orientation of the camera image. The value is the angle that the
+     * camera image needs to be rotated clockwise so it shows correctly on the
+     * display in its natural orientation. It must be 0, 90, 180, or 270.
+     *
+     * For example, suppose a device has a naturally tall screen. The
+     * back-facing camera sensor is mounted in landscape. You are looking at the
+     * screen. If the top side of the camera sensor is aligned with the right
+     * edge of the screen in natural orientation, the value must be 90. If the
+     * top side of a front-facing camera sensor is aligned with the right of the
+     * screen, the value must be 270.
+     *
+     * An external camera device must leave this set to 0.
+     *
+     */
+    uint32_t orientation;
+
+};
+
+/**
+ * Message types for ICameraDevice@1.0::enableMsgType()/disableMsgType()
+ *
+ * A set of bit masks for specifying how the received preview frames are
+ * handled before the previewCallback() call.
+ *
+ * The least significant 3 bits of an "int" value are used for this purpose:
+ *
+ * ..... 0 0 0
+ *       ^ ^ ^
+ *       | | |---------> determine whether the callback is enabled or not
+ *       | |-----------> determine whether the callback is one-shot or not
+ *       |-------------> determine whether the frame is copied out or not
+ *
+ * WARNING: When a frame is sent directly without copying, it is the frame
+ * receiver's responsiblity to make sure that the frame data won't get
+ * corrupted by subsequent preview frames filled by the camera. This flag is
+ * recommended only when copying out data brings significant performance price
+ * and the handling/processing of the received frame data is always faster than
+ * the preview frame rate so that data corruption won't occur.
+ *
+ * For instance,
+ * 1. 0x00 disables the callback. In this case, copy out and one shot bits
+ *    are ignored.
+ * 2. 0x01 enables a callback without copying out the received frames. A
+ *    typical use case is the Camcorder application to avoid making costly
+ *    frame copies.
+ * 3. 0x05 is enabling a callback with frame copied out repeatedly. A typical
+ *    use case is the Camera application.
+ * 4. 0x07 is enabling a callback with frame copied out only once. A typical
+ *    use case is the Barcode scanner application.
+ */
+enum FrameCallbackFlag : uint32_t {
+    ENABLE_MASK = 0x01,
+    ONE_SHOT_MASK = 0x02,
+    COPY_OUT_MASK = 0x04,
+    /** Typical use cases */
+    NOOP = 0x00,
+    CAMCORDER = 0x01,
+    CAMERA = 0x05,
+    BARCODE_SCANNER = 0x07
+};
+
+typedef bitfield<FrameCallbackFlag> FrameCallbackFlags;
+
+/**
+ * Subset of commands in /system/core/include/system/camera.h relevant for
+ * ICameraDevice@1.0::sendCommand()
+ */
+enum CommandType : uint32_t {
+    START_SMOOTH_ZOOM = 1,
+    STOP_SMOOTH_ZOOM = 2,
+
+    /**
+     * Start the face detection. This must be called only after preview is
+     * started.  The camera must notify the listener of CAMERA_MSG_FACE and the
+     * detected faces in the preview frame. The detected faces may be the same
+     * as the previous ones. Apps must call CAMERA_CMD_STOP_FACE_DETECTION to
+     * stop the face detection. This method is supported if CameraParameters
+     * KEY_MAX_NUM_HW_DETECTED_FACES or KEY_MAX_NUM_SW_DETECTED_FACES is bigger
+     * than 0. Hardware and software face detection must not be running at the
+     * same time. If the face detection has started, apps must not send this
+     * again.
+     *
+     * In hardware face detection mode, CameraParameters KEY_WHITE_BALANCE,
+     * KEY_FOCUS_AREAS and KEY_METERING_AREAS have no effect.
+     *
+     * arg1 is the face detection type. It can be CAMERA_FACE_DETECTION_HW or
+     * CAMERA_FACE_DETECTION_SW. If the type of face detection requested is not
+     * supported, the HAL must return BAD_VALUE.
+     */
+    START_FACE_DETECTION = 6,
+
+    /**
+     * Stop the face detection.
+     */
+    STOP_FACE_DETECTION = 7,
+
+    /**
+     * Enable/disable focus move callback (CAMERA_MSG_FOCUS_MOVE). Passing
+     * arg1 = 0 must disable, while passing arg1 = 1 must enable the callback.
+     */
+    ENABLE_FOCUS_MOVE_MSG = 8,
+
+    /**
+     * Configure an explicit format to use for video recording metadata mode.
+     * This can be used to switch the format from the
+     * default IMPLEMENTATION_DEFINED gralloc format to some other
+     * device-supported format, and the default dataspace from the BT_709 color
+     * space to some other device-supported dataspace. arg1 is the HAL pixel
+     * format, and arg2 is the HAL dataSpace. This command returns
+     * INVALID_OPERATION error if it is sent after video recording is started,
+     * or the command is not supported at all.
+     *
+     * If the gralloc format is set to a format other than
+     * IMPLEMENTATION_DEFINED, then HALv3 devices must use gralloc usage flags
+     * of SW_READ_OFTEN.
+     */
+    SET_VIDEO_FORMAT = 11
+};
+
+/**
+ * Message types for ICameraDevice1Callback::notifyCallback()
+ */
+enum NotifyCallbackMsg : uint32_t {
+    ERROR = 0x0001,
+    SHUTTER = 0x0002,
+    FOCUS = 0x0004,
+    ZOOM = 0x0008,
+    // Notify on autofocus start and stop. This is useful in continuous
+    // autofocus - FOCUS_MODE_CONTINUOUS_VIDEO and FOCUS_MODE_CONTINUOUS_PICTURE.
+    FOCUS_MOVE = 0x0800
+};
+
+/**
+ * Message types for ICameraDevice1Callback::dataCallback() and
+ * ICameraDevice1Callback::dataCallbackTimestamp()
+ */
+enum DataCallbackMsg : uint32_t {
+    PREVIEW_FRAME = 0x0010,
+    VIDEO_FRAME = 0x0020,
+    POSTVIEW_FRAME = 0x0040,
+    RAW_IMAGE = 0x0080,
+    COMPRESSED_IMAGE = 0x0100,
+    RAW_IMAGE_NOTIFY = 0x0200,
+    // Preview frame metadata. This can be combined with
+    // CAMERA_MSG_PREVIEW_FRAME in dataCallback. For example, the apps can
+    // request FRAME and METADATA. Or the apps can request only FRAME or only
+    // METADATA.
+    PREVIEW_METADATA = 0x0400
+};
+
+/*
+ * A simple integer handle to use to reference a particular memory buffer
+ * between the HAL and the framework.
+ */
+typedef uint32_t MemoryId;
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
new file mode 100644
index 0000000..8b72d5b
--- /dev/null
+++ b/camera/device/3.2/Android.bp
@@ -0,0 +1,78 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.camera.device@3.2_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.2",
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+        "ICameraDeviceSession.hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.2/types.cpp",
+        "android/hardware/camera/device/3.2/CameraDeviceAll.cpp",
+        "android/hardware/camera/device/3.2/CameraDeviceCallbackAll.cpp",
+        "android/hardware/camera/device/3.2/CameraDeviceSessionAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@3.2_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.2",
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+        "ICameraDeviceSession.hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.2/types.h",
+        "android/hardware/camera/device/3.2/ICameraDevice.h",
+        "android/hardware/camera/device/3.2/IHwCameraDevice.h",
+        "android/hardware/camera/device/3.2/BnHwCameraDevice.h",
+        "android/hardware/camera/device/3.2/BpHwCameraDevice.h",
+        "android/hardware/camera/device/3.2/BsCameraDevice.h",
+        "android/hardware/camera/device/3.2/ICameraDeviceCallback.h",
+        "android/hardware/camera/device/3.2/IHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/3.2/BnHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/3.2/BpHwCameraDeviceCallback.h",
+        "android/hardware/camera/device/3.2/BsCameraDeviceCallback.h",
+        "android/hardware/camera/device/3.2/ICameraDeviceSession.h",
+        "android/hardware/camera/device/3.2/IHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.2/BnHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.2/BpHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.2/BsCameraDeviceSession.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.device@3.2",
+    generated_sources: ["android.hardware.camera.device@3.2_genc++"],
+    generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/camera/device/3.2/ICameraDevice.hal b/camera/device/3.2/ICameraDevice.hal
new file mode 100644
index 0000000..6e66bf3
--- /dev/null
+++ b/camera/device/3.2/ICameraDevice.hal
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.2;
+
+import android.hardware.camera.common@1.0::types;
+import ICameraDeviceSession;
+import ICameraDeviceCallback;
+
+/**
+ * Camera device HAL, first modern version
+ *
+ * Supports the android.hardware.Camera API, and the android.hardware.camera2
+ * API at LIMITED or better hardware level.
+ *
+ */
+interface ICameraDevice {
+
+    /**
+     * Get camera device resource cost information.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On success
+     *     INTERNAL_ERROR:
+     *         An unexpected internal camera HAL error occurred, and the
+     *         resource cost is not available.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     * @return resourceCost
+     *     The resources required to open this camera device, or unspecified
+     *     values if status is not OK.
+     */
+    getResourceCost() generates (Status status, CameraResourceCost resourceCost);
+
+    /**
+     * getCameraCharacteristics:
+     *
+     * Return the static camera information for this camera device. This
+     * information may not change between consecutive calls.
+     *
+     * When an external camera is disconnected, its camera id becomes
+     * invalid. Calling this method with this invalid camera id must result in
+     * ILLEGAL_ARGUMENT; this may happen even before the device status callback
+     * is invoked by the HAL.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful open of the camera device.
+     *     INTERNAL_ERROR:
+     *         The camera device cannot be opened due to an internal
+     *         error.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     *
+     * @return cameraCharacteristics
+     *     The static metadata for this camera device, or an empty metadata
+     *     structure if status is not OK.
+     *
+     */
+    getCameraCharacteristics() generates
+            (Status status, CameraMetadata cameraCharacteristics);
+
+    /**
+     * setTorchMode:
+     *
+     * Turn on or off the torch mode of the flash unit associated with this
+     * camera device. If the operation is successful, HAL must notify the
+     * framework torch state by invoking
+     * ICameraProviderCallback::torchModeStatusChange() with the new state.
+     *
+     * An active camera session has a higher priority accessing the flash
+     * unit. When there are any resource conflicts, such as when open() is
+     * called to fully activate a camera device, the provider must notify the
+     * framework through ICameraProviderCallback::torchModeStatusChange() that
+     * the torch mode has been turned off and the torch mode state has become
+     * TORCH_MODE_STATUS_NOT_AVAILABLE. When resources to turn on torch mode
+     * become available again, the provider must notify the framework through
+     * ICameraProviderCallback::torchModeStatusChange() that the torch mode
+     * state has become TORCH_MODE_STATUS_AVAILABLE_OFF for set_torch_mode() to
+     * be called.
+     *
+     * When the client calls setTorchMode() to turn on the torch mode of a flash
+     * unit, if the HAL cannot keep multiple torch modes on simultaneously, the
+     * HAL must turn off the torch mode(s) that were turned on by previous
+     * setTorchMode() calls and notify the framework that the torch mode state
+     * of those flash unit(s) has become TORCH_MODE_STATUS_AVAILABLE_OFF.
+     *
+     * @param torchMode The new mode to set the device flash unit to.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful change to the torch state
+     *     INTERNAL_ERROR:
+     *         The flash unit cannot be operated due to an unexpected internal
+     *         error.
+     *     ILLEGAL_ARGUMENT:
+     *         The camera ID is unknown.
+     *     CAMERA_IN_USE:
+     *         This camera device has been opened, so the torch cannot be
+     *         controlled until it is closed.
+     *     MAX_CAMERAS_IN_USE:
+     *         Due to other camera devices being open, or due to other
+     *         resource constraints, the torch cannot be controlled currently.
+     *     METHOD_NOT_SUPPORTED:
+     *         This provider does not support direct operation of flashlight
+     *         torch mode. The framework must open the camera device and turn
+     *         the torch on through the device interface.
+     *     OPERATION_NOT_SUPPORTED:
+     *         This camera device does not have a flash unit. This can
+     *         be returned if and only if android.flash.info.available is
+     *         false.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     *
+     */
+    setTorchMode(TorchMode mode) generates (Status status);
+
+    /**
+     * open:
+     *
+     * Power on and initialize this camera device for active use, returning a
+     * session handle for active operations.
+     *
+     * @param callback Interface to invoke by the HAL for device asynchronous
+     *     events.
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful open of the camera device.
+     *     INTERNAL_ERROR:
+     *         The camera device cannot be opened due to an internal
+     *         error.
+     *     ILLEGAL_ARGUMENT:
+     *         The callbacks handle is invalid (for example, it is null).
+     *     CAMERA_IN_USE:
+     *         This camera device is already open.
+     *     MAX_CAMERAS_IN_USE:
+     *         The maximal number of camera devices that can be
+     *         opened concurrently were opened already.
+     *     CAMERA_DISCONNECTED:
+     *         This external camera device has been disconnected, and is no
+     *         longer available. This interface is now stale, and a new instance
+     *         must be acquired if the device is reconnected. All subsequent
+     *         calls on this interface must return CAMERA_DISCONNECTED.
+     * @return cameraDevice The interface to the newly-opened camera session,
+     *     or null if status is not OK.
+     */
+    open(ICameraDeviceCallback callback) generates
+            (Status status, ICameraDeviceSession session);
+
+    /**
+     * dumpState:
+     *
+     * Print out debugging state for the camera device. This may be called by
+     * the framework when the camera service is asked for a debug dump, which
+     * happens when using the dumpsys tool, or when capturing a bugreport.
+     *
+     * The passed-in file descriptor can be used to write debugging text using
+     * dprintf() or write(). The text must be in ASCII encoding only.
+     *
+     * In case this camera device has been disconnected, the dump must not fail,
+     * but may simply print out 'Device disconnected' or equivalent.
+     *
+     * Performance requirements:
+     *
+     * This must be a non-blocking call. The HAL should return from this call
+     * in 1ms, must return from this call in 10ms. This call must avoid
+     * deadlocks, as it may be called at any point during camera operation.
+     * Any synchronization primitives used (such as mutex locks or semaphores)
+     * must be acquired with a timeout.
+     */
+    dumpState(handle fd);
+
+};
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..753d085
--- /dev/null
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.2;
+
+import android.hardware.camera.common@1.0::types;
+
+/**
+ *
+ * Callback methods for the HAL to call into the framework.
+ *
+ * These methods are used to return metadata and image buffers for a completed
+ * or failed captures, and to notify the framework of asynchronous events such
+ * as errors.
+ *
+ * The framework must not call back into the HAL from within these callbacks,
+ * and these calls must not block for extended periods.
+ *
+ */
+interface ICameraDeviceCallback {
+
+    /**
+     * processCaptureResult:
+     *
+     * Send results from a completed capture to the framework.
+     * processCaptureResult() may be invoked multiple times by the HAL in
+     * response to a single capture request. This allows, for example, the
+     * metadata and low-resolution buffers to be returned in one call, and
+     * post-processed JPEG buffers in a later call, once it is available. Each
+     * call must include the frame number of the request it is returning
+     * metadata or buffers for.
+     *
+     * A component (buffer or metadata) of the complete result may only be
+     * included in one process_capture_result call. A buffer for each stream,
+     * and the result metadata, must be returned by the HAL for each request in
+     * one of the processCaptureResult calls, even in case of errors producing
+     * some of the output. A call to processCaptureResult() with neither
+     * output buffers or result metadata is not allowed.
+     *
+     * The order of returning metadata and buffers for a single result does not
+     * matter, but buffers for a given stream must be returned in FIFO order. So
+     * the buffer for request 5 for stream A must always be returned before the
+     * buffer for request 6 for stream A. This also applies to the result
+     * metadata; the metadata for request 5 must be returned before the metadata
+     * for request 6.
+     *
+     * However, different streams are independent of each other, so it is
+     * acceptable and expected that the buffer for request 5 for stream A may be
+     * returned after the buffer for request 6 for stream B is. And it is
+     * acceptable that the result metadata for request 6 for stream B is
+     * returned before the buffer for request 5 for stream A is.
+     *
+     * The HAL retains ownership of result structure, which only needs to be
+     * valid to access during this call. The framework must copy whatever it
+     * needs before this call returns.
+     *
+     * The output buffers do not need to be filled yet; the framework must wait
+     * on the stream buffer release sync fence before reading the buffer
+     * data. Therefore, this method should be called by the HAL as soon as
+     * possible, even if some or all of the output buffers are still in
+     * being filled. The HAL must include valid release sync fences into each
+     * output_buffers stream buffer entry, or -1 if that stream buffer is
+     * already filled.
+     *
+     * If the result buffer cannot be constructed for a request, the HAL must
+     * return an empty metadata buffer, but still provide the output buffers and
+     * their sync fences. In addition, notify() must be called with an
+     * ERROR_RESULT message.
+     *
+     * If an output buffer cannot be filled, its status field must be set to
+     * STATUS_ERROR. In addition, notify() must be called with a ERROR_BUFFER
+     * message.
+     *
+     * If the entire capture has failed, then this method still needs to be
+     * called to return the output buffers to the framework. All the buffer
+     * statuses must be STATUS_ERROR, and the result metadata must be an
+     * empty buffer. In addition, notify() must be called with a ERROR_REQUEST
+     * message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages
+     * must not be sent.
+     *
+     * Performance requirements:
+     *
+     * This is a non-blocking call. The framework must return this call in 5ms.
+     *
+     * The pipeline latency (see S7 for definition) should be less than or equal to
+     * 4 frame intervals, and must be less than or equal to 8 frame intervals.
+     *
+     */
+    processCaptureResult(CaptureResult result);
+
+    /**
+     * notify:
+     *
+     * Asynchronous notification callback from the HAL, fired for various
+     * reasons. Only for information independent of frame capture, or that
+     * require specific timing.
+     *
+     * Multiple threads may call notify() simultaneously.
+     *
+     * Buffers delivered to the framework must not be dispatched to the
+     * application layer until a start of exposure timestamp (or input image's
+     * start of exposure timestamp for a reprocess request) has been received
+     * via a SHUTTER notify() call. It is highly recommended to dispatch this
+     * call as early as possible.
+     *
+     * ------------------------------------------------------------------------
+     * Performance requirements:
+     *
+     * This is a non-blocking call. The framework must return this call in 5ms.
+     */
+    notify(NotifyMsg msg);
+
+};
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
new file mode 100644
index 0000000..e92d756
--- /dev/null
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -0,0 +1,362 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.2;
+
+import android.hardware.camera.common@1.0::types;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ *
+ */
+interface ICameraDeviceSession {
+
+    /**
+     * constructDefaultRequestSettings:
+     *
+     * Create capture settings for standard camera use cases.
+     *
+     * The device must return a settings buffer that is configured to meet the
+     * requested use case, which must be one of the CAMERA3_TEMPLATE_*
+     * enums. All request control fields must be included.
+     *
+     * Performance requirements:
+     *
+     * This must be a non-blocking call. The HAL should return from this call
+     * in 1ms, and must return from this call in 5ms.
+     *
+     * Return values:
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful construction of default settings.
+     *     INTERNAL_ERROR:
+     *         An unexpected internal error occurred, and the default settings
+     *         are not available.
+     *     ILLEGAL_ARGUMENT:
+     *         The camera HAL does not support the input template type
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     * @return template The default capture request settings for the requested
+     *     use case, or an empty metadata structure if status is not OK.
+     *
+     */
+    constructDefaultRequestSettings(RequestTemplate type) generates
+            (Status status, CameraMetadata requestTemplate);
+
+    /**
+     * configureStreams:
+     *
+     * Reset the HAL camera device processing pipeline and set up new input and
+     * output streams. This call replaces any existing stream configuration with
+     * the streams defined in the streamList. This method must be called at
+     * least once before a request is submitted with processCaptureRequest().
+     *
+     * The streamList must contain at least one output-capable stream, and may
+     * not contain more than one input-capable stream.
+     *
+     * The streamList may contain streams that are also in the currently-active
+     * set of streams (from the previous call to configureStreams()). These
+     * streams must already have valid values for usage, maxBuffers, and the
+     * private pointer.
+     *
+     * If the HAL needs to change the stream configuration for an existing
+     * stream due to the new configuration, it may rewrite the values of usage
+     * and/or maxBuffers during the configure call.
+     *
+     * The framework must detect such a change, and may then reallocate the
+     * stream buffers before using buffers from that stream in a request.
+     *
+     * If a currently-active stream is not included in streamList, the HAL may
+     * safely remove any references to that stream. It must not be reused in a
+     * later configureStreams() call by the framework, and all the gralloc
+     * buffers for it must be freed after the configureStreams() call returns.
+     *
+     * If the stream is new, the maxBuffer field of the stream structure must be
+     * set to 0. The usage must be set to the consumer usage flags. The HAL
+     * device must set these fields in the configureStreams() return values.
+     * These fields are then used by the framework and the platform gralloc
+     * module to allocate the gralloc buffers for each stream.
+     *
+     * Newly allocated buffers may be included in a capture request at any time
+     * by the framework. Once a gralloc buffer is returned to the framework
+     * with processCaptureResult (and its respective releaseFence has been
+     * signaled) the framework may free or reuse it at any time.
+     *
+     * ------------------------------------------------------------------------
+     *
+     * Preconditions:
+     *
+     * The framework must only call this method when no captures are being
+     * processed. That is, all results have been returned to the framework, and
+     * all in-flight input and output buffers have been returned and their
+     * release sync fences have been signaled by the HAL. The framework must not
+     * submit new requests for capture while the configureStreams() call is
+     * underway.
+     *
+     * Postconditions:
+     *
+     * The HAL device must configure itself to provide maximum possible output
+     * frame rate given the sizes and formats of the output streams, as
+     * documented in the camera device's static metadata.
+     *
+     * Performance requirements:
+     *
+     * This call is expected to be heavyweight and possibly take several hundred
+     * milliseconds to complete, since it may require resetting and
+     * reconfiguring the image sensor and the camera processing pipeline.
+     * Nevertheless, the HAL device should attempt to minimize the
+     * reconfiguration delay to minimize the user-visible pauses during
+     * application operational mode changes (such as switching from still
+     * capture to video recording).
+     *
+     * The HAL should return from this call in 500ms, and must return from this
+     * call in 1000ms.
+     *
+     * @return Status Status code for the operation, one of:
+     *     OK:
+     *          On successful stream configuration.
+     *     INTERNAL_ERROR:
+     *         If there has been a fatal error and the device is no longer
+     *         operational. Only close() can be called successfully by the
+     *         framework after this error is returned.
+     *     ILLEGAL_ARGUMENT:
+     *         If the requested stream configuration is invalid. Some examples
+     *         of invalid stream configurations include:
+     *           - Including more than 1 INPUT stream
+     *           - Not including any OUTPUT streams
+     *           - Including streams with unsupported formats, or an unsupported
+     *             size for that format.
+     *           - Including too many output streams of a certain format.
+     *           - Unsupported rotation configuration
+     *           - Stream sizes/formats don't satisfy the
+     *             camera3_stream_configuration_t->operation_mode requirements
+     *             for non-NORMAL mode, or the requested operation_mode is not
+     *             supported by the HAL.
+     *         The camera service cannot filter out all possible illegal stream
+     *         configurations, since some devices may support more simultaneous
+     *         streams or larger stream resolutions than the minimum required
+     *         for a given camera device hardware level. The HAL must return an
+     *         ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+     *         ready to accept a future valid stream configuration in a later
+     *         configureStreams call.
+     * @return finalConfiguration The stream parameters desired by the HAL for
+     *     each stream, including maximum buffers, the usage flags, and the
+     *     override format.
+     *
+     */
+    configureStreams(StreamConfiguration requestedConfiguration)
+            generates (Status status,
+                    HalStreamConfiguration halConfiguration);
+
+    /**
+     * processCaptureRequest:
+     *
+     * Send a new capture request to the HAL. The HAL must not return from
+     * this call until it is ready to accept the next request to process. Only
+     * one call to processCaptureRequest() must be made at a time by the
+     * framework, and the calls must all be from the same thread. The next call
+     * to processCaptureRequest() must be made as soon as a new request and
+     * its associated buffers are available. In a normal preview scenario, this
+     * means the function is generally called again by the framework almost
+     * instantly.
+     *
+     * The actual request processing is asynchronous, with the results of
+     * capture being returned by the HAL through the processCaptureResult()
+     * call. This call requires the result metadata to be available, but output
+     * buffers may simply provide sync fences to wait on. Multiple requests are
+     * expected to be in flight at once, to maintain full output frame rate.
+     *
+     * The framework retains ownership of the request structure. It is only
+     * guaranteed to be valid during this call. The HAL device must make copies
+     * of the information it needs to retain for the capture processing. The HAL
+     * is responsible for waiting on and closing the buffers' fences and
+     * returning the buffer handles to the framework.
+     *
+     * The HAL must write the file descriptor for the input buffer's release
+     * sync fence into input_buffer->release_fence, if input_buffer is not
+     * valid. If the HAL returns -1 for the input buffer release sync fence, the
+     * framework is free to immediately reuse the input buffer. Otherwise, the
+     * framework must wait on the sync fence before refilling and reusing the
+     * input buffer.
+     *
+     * The input/output buffers provided by the framework in each request
+     * may be brand new (having never before seen by the HAL).
+     *
+     * ------------------------------------------------------------------------
+     * Performance considerations:
+     *
+     * Handling a new buffer should be extremely lightweight and there must be
+     * no frame rate degradation or frame jitter introduced.
+     *
+     * This call must return fast enough to ensure that the requested frame
+     * rate can be sustained, especially for streaming cases (post-processing
+     * quality settings set to FAST). The HAL should return this call in 1
+     * frame interval, and must return from this call in 4 frame intervals.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful start to processing the capture request
+     *     ILLEGAL_ARGUMENT:
+     *         If the input is malformed (the settings are empty when not
+     *         allowed, there are 0 output buffers, etc) and capture processing
+     *         cannot start. Failures during request processing must be
+     *         handled by calling ICameraDeviceCallback::notify(). In case of
+     *         this error, the framework retains responsibility for the
+     *         stream buffers' fences and the buffer handles; the HAL must not
+     *         close the fences or return these buffers with
+     *         ICameraDeviceCallback::processCaptureResult().
+     *     INTERNAL_ERROR:
+     *         If the camera device has encountered a serious error. After this
+     *         error is returned, only the close() method can be successfully
+     *         called by the framework.
+     *
+     */
+    processCaptureRequest(CaptureRequest request)
+            generates (Status status);
+
+    /**
+     * flush:
+     *
+     * Flush all currently in-process captures and all buffers in the pipeline
+     * on the given device. Generally, this method is used to dump all state as
+     * quickly as possible in order to prepare for a configure_streams() call.
+     *
+     * No buffers are required to be successfully returned, so every buffer
+     * held at the time of flush() (whether successfully filled or not) may be
+     * returned with CAMERA3_BUFFER_STATUS_ERROR. Note the HAL is still allowed
+     * to return valid (CAMERA3_BUFFER_STATUS_OK) buffers during this call,
+     * provided they are successfully filled.
+     *
+     * All requests currently in the HAL are expected to be returned as soon as
+     * possible. Not-in-process requests must return errors immediately. Any
+     * interruptible hardware blocks must be stopped, and any uninterruptible
+     * blocks must be waited on.
+     *
+     * flush() may be called concurrently to processCaptureRequest(), with the
+     * expectation that processCaptureRequest returns quickly and the
+     * request submitted in that processCaptureRequest call is treated like
+     * all other in-flight requests. Due to concurrency issues, it is possible
+     * that from the HAL's point of view, a processCaptureRequest() call may
+     * be started after flush has been invoked but has not returned yet. If such
+     * a call happens before flush() returns, the HAL must treat the new
+     * capture request like other in-flight pending requests (see #4 below).
+     *
+     * More specifically, the HAL must follow below requirements for various
+     * cases:
+     *
+     * 1. For captures that are too late for the HAL to cancel/stop, and must be
+     *    completed normally by the HAL; i.e. the HAL can send shutter/notify
+     *    and processCaptureResult and buffers as normal.
+     *
+     * 2. For pending requests that have not done any processing, the HAL must
+     *    call notify CAMERA3_MSG_ERROR_REQUEST, and return all the output
+     *    buffers with processCaptureResult in the error state
+     *    (CAMERA3_BUFFER_STATUS_ERROR). The HAL must not place the release
+     *    fence into an error state, instead, the release fences must be set to
+     *    the acquire fences passed by the framework, or -1 if they have been
+     *    waited on by the HAL already. This is also the path to follow for any
+     *    captures for which the HAL already called notify() with
+     *    CAMERA3_MSG_SHUTTER but won't be producing any metadata/valid buffers
+     *    for. After CAMERA3_MSG_ERROR_REQUEST, for a given frame, only
+     *    processCaptureResults with buffers in CAMERA3_BUFFER_STATUS_ERROR
+     *    are allowed. No further notifys or processCaptureResult with
+     *    non-empty metadata is allowed.
+     *
+     * 3. For partially completed pending requests that do not have all the
+     *    output buffers or perhaps missing metadata, the HAL must follow
+     *    below:
+     *
+     *    3.1. Call notify with CAMERA3_MSG_ERROR_RESULT if some of the expected
+     *         result metadata (i.e. one or more partial metadata) won't be
+     *         available for the capture.
+     *
+     *    3.2. Call notify with CAMERA3_MSG_ERROR_BUFFER for every buffer that
+     *         won't be produced for the capture.
+     *
+     *    3.3. Call notify with CAMERA3_MSG_SHUTTER with the capture timestamp
+     *         before any buffers/metadata are returned with
+     *         processCaptureResult.
+     *
+     *    3.4. For captures that will produce some results, the HAL must not
+     *         call CAMERA3_MSG_ERROR_REQUEST, since that indicates complete
+     *         failure.
+     *
+     *    3.5. Valid buffers/metadata must be passed to the framework as
+     *         normal.
+     *
+     *    3.6. Failed buffers must be returned to the framework as described
+     *         for case 2. But failed buffers do not have to follow the strict
+     *         ordering valid buffers do, and may be out-of-order with respect
+     *         to valid buffers. For example, if buffers A, B, C, D, E are sent,
+     *         D and E are failed, then A, E, B, D, C is an acceptable return
+     *         order.
+     *
+     *    3.7. For fully-missing metadata, calling CAMERA3_MSG_ERROR_RESULT is
+     *         sufficient, no need to call processCaptureResult with empty
+     *         metadata or equivalent.
+     *
+     * 4. If a flush() is invoked while a processCaptureRequest() invocation
+     *    is active, that process call must return as soon as possible. In
+     *    addition, if a processCaptureRequest() call is made after flush()
+     *    has been invoked but before flush() has returned, the capture request
+     *    provided by the late processCaptureRequest call must be treated
+     *    like a pending request in case #2 above.
+     *
+     * flush() must only return when there are no more outstanding buffers or
+     * requests left in the HAL. The framework may call configure_streams (as
+     * the HAL state is now quiesced) or may issue new requests.
+     *
+     * Note that it's sufficient to only support fully-succeeded and
+     * fully-failed result cases. However, it is highly desirable to support
+     * the partial failure cases as well, as it could help improve the flush
+     * call overall performance.
+     *
+     * Performance requirements:
+     *
+     * The HAL should return from this call in 100ms, and must return from this
+     * call in 1000ms. And this call must not be blocked longer than pipeline
+     * latency (see S7 for definition).
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful flush of the camera HAL.
+     *     INTERNAL_ERROR:
+     *         If the camera device has encountered a serious error. After this
+     *         error is returned, only the close() method can be successfully
+     *         called by the framework.
+     */
+    flush() generates (Status status);
+
+    /**
+     * close:
+     *
+     * Shut down the camera device.
+     *
+     * After this call, all calls to this session instance must return
+     * INTERNAL_ERROR.
+     *
+     * This method must always succeed, even if the device has encountered a
+     * serious error.
+     */
+    close();
+};
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
new file mode 100644
index 0000000..40d4253
--- /dev/null
+++ b/camera/device/3.2/default/Android.bp
@@ -0,0 +1,46 @@
+cc_library_shared {
+    name: "android.hardware.camera.device@3.2-impl",
+    srcs: ["CameraDevice.cpp",
+           "CameraDeviceSession.cpp",
+           "convert.cpp"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.provider@2.4",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata"
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ],
+    export_include_dirs: ["."]
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.device@3.2-impl-binderized",
+    srcs: ["CameraDevice.cpp",
+           "CameraDeviceSession.cpp",
+           "convert.cpp"],
+    cppflags: ["-DBINDERIZED"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.provider@2.4",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata"
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ],
+    export_include_dirs: ["."]
+}
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
new file mode 100644
index 0000000..18e0e7b
--- /dev/null
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamDev@3.2-impl"
+#include <android/log.h>
+
+#include <utils/Vector.h>
+#include <utils/Trace.h>
+#include "CameraDevice.h"
+#include <include/convert.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+using ::android::hardware::camera::common::V1_0::Status;
+
+CameraDevice::CameraDevice(
+    sp<CameraModule> module, const std::string& cameraId,
+    const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
+        mModule(module),
+        mCameraId(cameraId),
+        mDisconnected(false),
+        mCameraDeviceNames(cameraDeviceNames) {
+    mCameraIdInt = atoi(mCameraId.c_str());
+    // Should not reach here as provider also validate ID
+    if (mCameraIdInt < 0 || mCameraIdInt >= module->getNumberOfCameras()) {
+        ALOGE("%s: Invalid camera id: %s", __FUNCTION__, mCameraId.c_str());
+        mInitFail = true;
+    }
+
+    mDeviceVersion = mModule->getDeviceVersion(mCameraIdInt);
+    if (mDeviceVersion < CAMERA_DEVICE_API_VERSION_3_2) {
+        ALOGE("%s: Camera id %s does not support HAL3.2+",
+                __FUNCTION__, mCameraId.c_str());
+        mInitFail = true;
+    }
+}
+
+CameraDevice::~CameraDevice() {}
+
+Status CameraDevice::initStatus() const {
+    Mutex::Autolock _l(mLock);
+    Status status = Status::OK;
+    if (mInitFail) {
+        status = Status::INTERNAL_ERROR;
+    } else if (mDisconnected) {
+        status = Status::CAMERA_DISCONNECTED;
+    }
+    return status;
+}
+
+void CameraDevice::setConnectionStatus(bool connected) {
+    Mutex::Autolock _l(mLock);
+    mDisconnected = !connected;
+    if (mSession == nullptr) {
+        return;
+    }
+    sp<CameraDeviceSession> session = mSession.promote();
+    if (session == nullptr) {
+        return;
+    }
+    // Only notify active session disconnect events.
+    // Users will need to re-open camera after disconnect event
+    if (!connected) {
+        session->disconnect();
+    }
+    return;
+}
+
+Status CameraDevice::getHidlStatus(int status) {
+    switch (status) {
+        case 0: return Status::OK;
+        case -ENOSYS: return Status::OPERATION_NOT_SUPPORTED;
+        case -EBUSY : return Status::CAMERA_IN_USE;
+        case -EUSERS: return Status::MAX_CAMERAS_IN_USE;
+        case -ENODEV: return Status::INTERNAL_ERROR;
+        case -EINVAL: return Status::ILLEGAL_ARGUMENT;
+        default:
+            ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
+            return Status::INTERNAL_ERROR;
+    }
+}
+
+// Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
+Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb)  {
+    Status status = initStatus();
+    CameraResourceCost resCost;
+    if (status == Status::OK) {
+        int cost = 100;
+        std::vector<std::string> conflicting_devices;
+        struct camera_info info;
+
+        // If using post-2.4 module version, query the cost + conflicting devices from the HAL
+        if (mModule->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4) {
+            int ret = mModule->getCameraInfo(mCameraIdInt, &info);
+            if (ret == OK) {
+                cost = info.resource_cost;
+                for (size_t i = 0; i < info.conflicting_devices_length; i++) {
+                    std::string cameraId(info.conflicting_devices[i]);
+                    for (const auto& pair : mCameraDeviceNames) {
+                        if (cameraId == pair.first) {
+                            conflicting_devices.push_back(pair.second);
+                        }
+                    }
+                }
+            } else {
+                status = Status::INTERNAL_ERROR;
+            }
+        }
+
+        if (status == Status::OK) {
+            resCost.resourceCost = cost;
+            resCost.conflictingDevices.resize(conflicting_devices.size());
+            for (size_t i = 0; i < conflicting_devices.size(); i++) {
+                resCost.conflictingDevices[i] = conflicting_devices[i];
+                ALOGV("CamDevice %s is conflicting with camDevice %s",
+                        mCameraId.c_str(), resCost.conflictingDevices[i].c_str());
+            }
+        }
+    }
+    _hidl_cb(status, resCost);
+    return Void();
+}
+
+Return<void> CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb)  {
+    Status status = initStatus();
+    CameraMetadata cameraCharacteristics;
+    if (status == Status::OK) {
+        //Module 2.1+ codepath.
+        struct camera_info info;
+        int ret = mModule->getCameraInfo(mCameraIdInt, &info);
+        if (ret == OK) {
+            convertToHidl(info.static_camera_characteristics, &cameraCharacteristics);
+        } else {
+            ALOGE("%s: get camera info failed!", __FUNCTION__);
+            status = Status::INTERNAL_ERROR;
+        }
+    }
+    _hidl_cb(status, cameraCharacteristics);
+    return Void();
+}
+
+Return<Status> CameraDevice::setTorchMode(TorchMode mode)  {
+    if (!mModule->isSetTorchModeSupported()) {
+        return Status::METHOD_NOT_SUPPORTED;
+    }
+
+    Status status = initStatus();
+    if (status == Status::OK) {
+        bool enable = (mode == TorchMode::ON) ? true : false;
+        status = getHidlStatus(mModule->setTorchMode(mCameraId.c_str(), enable));
+    }
+    return status;
+}
+
+Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
+    Status status = initStatus();
+    sp<CameraDeviceSession> session = nullptr;
+
+    if (callback == nullptr) {
+        ALOGE("%s: cannot open camera %s. callback is null!",
+                __FUNCTION__, mCameraId.c_str());
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, session);
+        return Void();
+    }
+
+    if (status != Status::OK) {
+        // Provider will never pass initFailed device to client, so
+        // this must be a disconnected camera
+        ALOGE("%s: cannot open camera %s. camera is disconnected!",
+                __FUNCTION__, mCameraId.c_str());
+        _hidl_cb(Status::CAMERA_DISCONNECTED, session);
+        return Void();
+    } else {
+        mLock.lock();
+
+        ALOGV("%s: Initializing device for camera %d", __FUNCTION__, mCameraIdInt);
+        session = mSession.promote();
+        if (session != nullptr && !session->isClosed()) {
+            ALOGE("%s: cannot open an already opened camera!", __FUNCTION__);
+            mLock.unlock();
+            _hidl_cb(Status::CAMERA_IN_USE, nullptr);
+            return Void();
+        }
+
+        /** Open HAL device */
+        status_t res;
+        camera3_device_t *device;
+
+        ATRACE_BEGIN("camera3->open");
+        res = mModule->open(mCameraId.c_str(),
+                reinterpret_cast<hw_device_t**>(&device));
+        ATRACE_END();
+
+        if (res != OK) {
+            ALOGE("%s: cannot open camera %s!", __FUNCTION__, mCameraId.c_str());
+            mLock.unlock();
+            _hidl_cb(getHidlStatus(res), nullptr);
+            return Void();
+        }
+
+        /** Cross-check device version */
+        if (device->common.version < CAMERA_DEVICE_API_VERSION_3_2) {
+            ALOGE("%s: Could not open camera: "
+                    "Camera device should be at least %x, reports %x instead",
+                    __FUNCTION__,
+                    CAMERA_DEVICE_API_VERSION_3_2,
+                    device->common.version);
+            device->common.close(&device->common);
+            mLock.unlock();
+            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+            return Void();
+        }
+
+        session = new CameraDeviceSession(device, callback);
+        if (session == nullptr) {
+            ALOGE("%s: camera device session allocation failed", __FUNCTION__);
+            mLock.unlock();
+            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+            return Void();
+        }
+        if (session->isInitFailed()) {
+            ALOGE("%s: camera device session init failed", __FUNCTION__);
+            session = nullptr;
+            mLock.unlock();
+            _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+            return Void();
+        }
+        mSession = session;
+        mLock.unlock();
+    }
+    _hidl_cb(status, session);
+    return Void();
+}
+
+Return<void> CameraDevice::dumpState(const ::android::hardware::hidl_handle& handle)  {
+    Mutex::Autolock _l(mLock);
+    if (handle.getNativeHandle() == nullptr) {
+        ALOGE("%s: handle must not be null", __FUNCTION__);
+        return Void();
+    }
+    if (handle->numFds != 1 || handle->numInts != 0) {
+        ALOGE("%s: handle must contain 1 FD and 0 integers! Got %d FDs and %d ints",
+                __FUNCTION__, handle->numFds, handle->numInts);
+        return Void();
+    }
+    int fd = handle->data[0];
+    if (mSession == nullptr) {
+        dprintf(fd, "No active camera device session instance\n");
+        return Void();
+    }
+    sp<CameraDeviceSession> session = mSession.promote();
+    if (session == nullptr) {
+        dprintf(fd, "No active camera device session instance\n");
+        return Void();
+    }
+    // Call into active session to dump states
+    session->dumpState(handle);
+    return Void();
+}
+// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
+
+} // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.2/default/CameraDevice.h b/camera/device/3.2/default/CameraDevice.h
new file mode 100644
index 0000000..317eea5
--- /dev/null
+++ b/camera/device/3.2/default/CameraDevice.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE_H
+
+#include "utils/Mutex.h"
+#include "CameraModule.h"
+#include "CameraMetadata.h"
+#include "CameraDeviceSession.h"
+
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+using ::android::hardware::camera::device::V3_2::ICameraDevice;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::common::V1_0::CameraResourceCost;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+/*
+ * The camera device HAL implementation is opened lazily (via the open call)
+ */
+struct CameraDevice : public ICameraDevice {
+    // Called by provider HAL. Provider HAL must ensure the uniqueness of
+    // CameraDevice object per cameraId, or there could be multiple CameraDevice
+    // trying to access the same physical camera.
+    // Also, provider will have to keep track of all CameraDevice object in
+    // order to notify CameraDevice when the underlying camera is detached
+    CameraDevice(sp<CameraModule> module,
+                 const std::string& cameraId,
+                 const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
+    ~CameraDevice();
+    // Caller must use this method to check if CameraDevice ctor failed
+    bool isInitFailed() { return mInitFail; }
+    // Used by provider HAL to signal external camera disconnected
+    void setConnectionStatus(bool connected);
+
+    /* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
+    // The following method can be called without opening the actual camera device
+    Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
+    Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
+    Return<Status> setTorchMode(TorchMode mode) override;
+
+    // Open the device HAL and also return a default capture session
+    Return<void> open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) override;
+
+
+    // Forward the dump call to the opened session, or do nothing
+    Return<void> dumpState(const ::android::hardware::hidl_handle& fd) override;
+    /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
+
+private:
+    // Passed from provider HAL. Should not change.
+    sp<CameraModule> mModule;
+    const std::string mCameraId;
+    // const after ctor
+    int   mCameraIdInt;
+    int   mDeviceVersion;
+    bool  mInitFail = false;
+    // Set by provider (when external camera is connected/disconnected)
+    bool  mDisconnected;
+    wp<CameraDeviceSession> mSession = nullptr;
+
+    const SortedVector<std::pair<std::string, std::string>>& mCameraDeviceNames;
+
+    // gating access to mSession and mDisconnected
+    mutable Mutex mLock;
+
+    // convert conventional HAL status to HIDL Status
+    static Status getHidlStatus(int);
+
+    Status initStatus() const;
+};
+
+}  // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE_H
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
new file mode 100644
index 0000000..26b7b73
--- /dev/null
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -0,0 +1,747 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamDevSession@3.2-impl"
+#include <android/log.h>
+
+#include <utils/Trace.h>
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
+#include "CameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+namespace {
+
+// Copy pasted from Hwc.cpp. Use this until gralloc mapper HAL is working
+class HandleImporter {
+public:
+    HandleImporter() : mInitialized(false) {}
+
+    bool initialize()
+    {
+        // allow only one client
+        if (mInitialized) {
+            return false;
+        }
+
+        if (!openGralloc()) {
+            return false;
+        }
+
+        mInitialized = true;
+        return true;
+    }
+
+    void cleanup()
+    {
+        if (!mInitialized) {
+            return;
+        }
+
+        closeGralloc();
+        mInitialized = false;
+    }
+
+    // In IComposer, any buffer_handle_t is owned by the caller and we need to
+    // make a clone for hwcomposer2.  We also need to translate empty handle
+    // to nullptr.  This function does that, in-place.
+    bool importBuffer(buffer_handle_t& handle)
+    {
+        if (!handle->numFds && !handle->numInts) {
+            handle = nullptr;
+            return true;
+        }
+
+        buffer_handle_t clone = cloneBuffer(handle);
+        if (!clone) {
+            return false;
+        }
+
+        handle = clone;
+        return true;
+    }
+
+    void freeBuffer(buffer_handle_t handle)
+    {
+        if (!handle) {
+            return;
+        }
+
+        releaseBuffer(handle);
+    }
+
+    bool importFence(const native_handle_t* handle, int& fd)
+    {
+        if (handle == nullptr || handle->numFds == 0) {
+            fd = -1;
+        } else if (handle->numFds == 1) {
+            fd = dup(handle->data[0]);
+            if (fd < 0) {
+                ALOGE("failed to dup fence fd %d", handle->data[0]);
+                return false;
+            }
+        } else {
+            ALOGE("invalid fence handle with %d file descriptors",
+                    handle->numFds);
+            return false;
+        }
+
+        return true;
+    }
+
+    void closeFence(int fd)
+    {
+        if (fd >= 0) {
+            close(fd);
+        }
+    }
+
+private:
+    bool mInitialized;
+
+    // Some existing gralloc drivers do not support retaining more than once,
+    // when we are in passthrough mode.
+#ifdef BINDERIZED
+    bool openGralloc()
+    {
+        const hw_module_t* module;
+        int err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module);
+        if (err) {
+            ALOGE("failed to get gralloc module");
+            return false;
+        }
+
+        uint8_t major = (module->module_api_version >> 8) & 0xff;
+        if (major > 1) {
+            ALOGE("unknown gralloc module major version %d", major);
+            return false;
+        }
+
+        if (major == 1) {
+            err = gralloc1_open(module, &mDevice);
+            if (err) {
+                ALOGE("failed to open gralloc1 device");
+                return false;
+            }
+
+            mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
+                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
+            mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
+                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
+            if (!mRetain || !mRelease) {
+                ALOGE("invalid gralloc1 device");
+                gralloc1_close(mDevice);
+                return false;
+            }
+        } else {
+            mModule = reinterpret_cast<const gralloc_module_t*>(module);
+        }
+
+        return true;
+    }
+
+    void closeGralloc()
+    {
+        if (mDevice) {
+            gralloc1_close(mDevice);
+        }
+    }
+
+    buffer_handle_t cloneBuffer(buffer_handle_t handle)
+    {
+        native_handle_t* clone = native_handle_clone(handle);
+        if (!clone) {
+            ALOGE("failed to clone buffer %p", handle);
+            return nullptr;
+        }
+
+        bool err;
+        if (mDevice) {
+            err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
+        } else {
+            err = (mModule->registerBuffer(mModule, clone) != 0);
+        }
+
+        if (err) {
+            ALOGE("failed to retain/register buffer %p", clone);
+            native_handle_close(clone);
+            native_handle_delete(clone);
+            return nullptr;
+        }
+
+        return clone;
+    }
+
+    void releaseBuffer(buffer_handle_t handle)
+    {
+        if (mDevice) {
+            mRelease(mDevice, handle);
+        } else {
+            mModule->unregisterBuffer(mModule, handle);
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle_t*>(handle));
+        }
+    }
+
+    // gralloc1
+    gralloc1_device_t* mDevice;
+    GRALLOC1_PFN_RETAIN mRetain;
+    GRALLOC1_PFN_RELEASE mRelease;
+
+    // gralloc0
+    const gralloc_module_t* mModule;
+#else
+    bool openGralloc() { return true; }
+    void closeGralloc() {}
+    buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
+    void releaseBuffer(buffer_handle_t) {}
+#endif
+};
+
+HandleImporter sHandleImporter;
+
+} // Anonymous namespace
+
+CameraDeviceSession::CameraDeviceSession(
+    camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
+        camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
+        mDevice(device),
+        mCallback(callback) {
+    // For now, we init sHandleImporter but do not cleanup (keep it alive until
+    // HAL process ends)
+    sHandleImporter.initialize();
+
+    mInitFail = initialize();
+}
+
+bool CameraDeviceSession::initialize() {
+    /** Initialize device with callback functions */
+    ATRACE_BEGIN("camera3->initialize");
+    status_t res = mDevice->ops->initialize(mDevice, this);
+    ATRACE_END();
+
+    if (res != OK) {
+        ALOGE("%s: Unable to initialize HAL device: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        mDevice->common.close(&mDevice->common);
+        mClosed = true;
+        return true;
+    }
+    return false;
+}
+
+CameraDeviceSession::~CameraDeviceSession() {
+    if (!isClosed()) {
+        ALOGE("CameraDeviceSession deleted before close!");
+        close();
+    }
+}
+
+bool CameraDeviceSession::isClosed() {
+    Mutex::Autolock _l(mStateLock);
+    return mClosed;
+}
+
+Status CameraDeviceSession::initStatus() const {
+    Mutex::Autolock _l(mStateLock);
+    Status status = Status::OK;
+    if (mInitFail) {
+        status = Status::INTERNAL_ERROR;
+    } else if (mDisconnected) {
+        status = Status::CAMERA_DISCONNECTED;
+    } else if (mClosed) {
+        status = Status::INTERNAL_ERROR;
+    }
+    return status;
+}
+
+void CameraDeviceSession::disconnect() {
+    Mutex::Autolock _l(mStateLock);
+    mDisconnected = true;
+    ALOGW("%s: Camera device is disconnected. Closing.", __FUNCTION__);
+    if (!mClosed) {
+        mDevice->common.close(&mDevice->common);
+        mClosed = true;
+    }
+}
+
+void CameraDeviceSession::dumpState(const native_handle_t* fd) {
+    if (!isClosed()) {
+        mDevice->ops->dump(mDevice, fd->data[0]);
+    }
+}
+
+Status CameraDeviceSession::importRequest(
+        const CaptureRequest& request,
+        hidl_vec<buffer_handle_t*>& allBufPtrs,
+        hidl_vec<int>& allFences) {
+    bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
+            request.inputBuffer.bufferId != 0);
+    size_t numOutputBufs = request.outputBuffers.size();
+    size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
+    // Validate all I/O buffers
+    hidl_vec<buffer_handle_t> allBufs;
+    hidl_vec<uint64_t> allBufIds;
+    allBufs.resize(numBufs);
+    allBufIds.resize(numBufs);
+    allBufPtrs.resize(numBufs);
+    allFences.resize(numBufs);
+    std::vector<int32_t> streamIds(numBufs);
+
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        allBufs[i] = request.outputBuffers[i].buffer.getNativeHandle();
+        allBufIds[i] = request.outputBuffers[i].bufferId;
+        allBufPtrs[i] = &allBufs[i];
+        streamIds[i] = request.outputBuffers[i].streamId;
+    }
+    if (hasInputBuf) {
+        allBufs[numOutputBufs] = request.inputBuffer.buffer.getNativeHandle();
+        allBufIds[numOutputBufs] = request.inputBuffer.bufferId;
+        allBufPtrs[numOutputBufs] = &allBufs[numOutputBufs];
+        streamIds[numOutputBufs] = request.inputBuffer.streamId;
+    }
+
+    for (size_t i = 0; i < numBufs; i++) {
+        buffer_handle_t buf = allBufs[i];
+        uint64_t bufId = allBufIds[i];
+        CirculatingBuffers& cbs = mCirculatingBuffers[streamIds[i]];
+        if (cbs.count(bufId) == 0) {
+            if (buf == nullptr) {
+                ALOGE("%s: bufferId %" PRIu64 " has null buffer handle!", __FUNCTION__, bufId);
+                return Status::ILLEGAL_ARGUMENT;
+            }
+            // Register a newly seen buffer
+            buffer_handle_t importedBuf = buf;
+            sHandleImporter.importBuffer(importedBuf);
+            if (importedBuf == nullptr) {
+                ALOGE("%s: output buffer %zu is invalid!", __FUNCTION__, i);
+                return Status::INTERNAL_ERROR;
+            } else {
+                cbs[bufId] = importedBuf;
+            }
+        }
+        allBufPtrs[i] = &cbs[bufId];
+    }
+
+    // All buffers are imported. Now validate output buffer acquire fences
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        if (!sHandleImporter.importFence(
+                request.outputBuffers[i].acquireFence, allFences[i])) {
+            ALOGE("%s: output buffer %zu acquire fence is invalid", __FUNCTION__, i);
+            cleanupInflightFences(allFences, i);
+            return Status::INTERNAL_ERROR;
+        }
+    }
+
+    // Validate input buffer acquire fences
+    if (hasInputBuf) {
+        if (!sHandleImporter.importFence(
+                request.inputBuffer.acquireFence, allFences[numOutputBufs])) {
+            ALOGE("%s: input buffer acquire fence is invalid", __FUNCTION__);
+            cleanupInflightFences(allFences, numOutputBufs);
+            return Status::INTERNAL_ERROR;
+        }
+    }
+    return Status::OK;
+}
+
+void CameraDeviceSession::cleanupInflightFences(
+        hidl_vec<int>& allFences, size_t numFences) {
+    for (size_t j = 0; j < numFences; j++) {
+        sHandleImporter.closeFence(allFences[j]);
+    }
+}
+
+// Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
+Return<void> CameraDeviceSession::constructDefaultRequestSettings(
+        RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb)  {
+    Status status = initStatus();
+    CameraMetadata outMetadata;
+    const camera_metadata_t *rawRequest;
+    if (status == Status::OK) {
+        ATRACE_BEGIN("camera3->construct_default_request_settings");
+        rawRequest = mDevice->ops->construct_default_request_settings(mDevice, (int) type);
+        ATRACE_END();
+        if (rawRequest == nullptr) {
+            ALOGI("%s: template %d is not supported on this camera device",
+                  __FUNCTION__, type);
+            status = Status::ILLEGAL_ARGUMENT;
+        } else {
+            convertToHidl(rawRequest, &outMetadata);
+        }
+    }
+    _hidl_cb(status, outMetadata);
+    return Void();
+}
+
+Return<void> CameraDeviceSession::configureStreams(
+        const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb)  {
+    Status status = initStatus();
+    HalStreamConfiguration outStreams;
+
+    // hold the inflight lock for entire configureStreams scope since there must not be any
+    // inflight request/results during stream configuration.
+    Mutex::Autolock _l(mInflightLock);
+    if (!mInflightBuffers.empty()) {
+        ALOGE("%s: trying to configureStreams while there are still %zu inflight buffers!",
+                __FUNCTION__, mInflightBuffers.size());
+        _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+        return Void();
+    }
+
+
+
+    if (status == Status::OK) {
+        camera3_stream_configuration_t stream_list;
+        hidl_vec<camera3_stream_t*> streams;
+
+        stream_list.operation_mode = (uint32_t) requestedConfiguration.operationMode;
+        stream_list.num_streams = requestedConfiguration.streams.size();
+        streams.resize(stream_list.num_streams);
+        stream_list.streams = streams.data();
+
+        for (uint32_t i = 0; i < stream_list.num_streams; i++) {
+            int id = requestedConfiguration.streams[i].id;
+
+            if (mStreamMap.count(id) == 0) {
+                Camera3Stream stream;
+                convertFromHidl(requestedConfiguration.streams[i], &stream);
+                mStreamMap[id] = stream;
+                mCirculatingBuffers.emplace(stream.mId, CirculatingBuffers{});
+            } else {
+                // width/height/format must not change, but usage/rotation might need to change
+                if (mStreamMap[id].stream_type !=
+                        (int) requestedConfiguration.streams[i].streamType ||
+                        mStreamMap[id].width != requestedConfiguration.streams[i].width ||
+                        mStreamMap[id].height != requestedConfiguration.streams[i].height ||
+                        mStreamMap[id].format != (int) requestedConfiguration.streams[i].format ||
+                        mStreamMap[id].data_space != (android_dataspace_t)
+                                requestedConfiguration.streams[i].dataSpace) {
+                    ALOGE("%s: stream %d configuration changed!", __FUNCTION__, id);
+                    _hidl_cb(Status::INTERNAL_ERROR, outStreams);
+                    return Void();
+                }
+                mStreamMap[id].rotation = (int) requestedConfiguration.streams[i].rotation;
+                mStreamMap[id].usage = (uint32_t) requestedConfiguration.streams[i].usage;
+            }
+            streams[i] = &mStreamMap[id];
+        }
+
+        ATRACE_BEGIN("camera3->configure_streams");
+        status_t ret = mDevice->ops->configure_streams(mDevice, &stream_list);
+        ATRACE_END();
+
+        // delete unused streams, note we do this after adding new streams to ensure new stream
+        // will not have the same address as deleted stream, and HAL has a chance to reference
+        // the to be deleted stream in configure_streams call
+        for(auto it = mStreamMap.begin(); it != mStreamMap.end();) {
+            int id = it->first;
+            bool found = false;
+            for (const auto& stream : requestedConfiguration.streams) {
+                if (id == stream.id) {
+                    found = true;
+                    break;
+                }
+            }
+            if (!found) {
+                // Unmap all buffers of deleted stream
+                for (auto& pair : mCirculatingBuffers.at(id)) {
+                    sHandleImporter.freeBuffer(pair.second);
+                }
+                mCirculatingBuffers[id].clear();
+                mCirculatingBuffers.erase(id);
+                it = mStreamMap.erase(it);
+            } else {
+                ++it;
+            }
+        }
+
+        if (ret == -EINVAL) {
+            status = Status::ILLEGAL_ARGUMENT;
+        } else if (ret != OK) {
+            status = Status::INTERNAL_ERROR;
+        } else {
+            convertToHidl(stream_list, &outStreams);
+        }
+
+    }
+    _hidl_cb(status, outStreams);
+    return Void();
+}
+
+Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request)  {
+    Status status = initStatus();
+    if (status != Status::OK) {
+        ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
+        return status;
+    }
+
+    camera3_capture_request_t halRequest;
+    halRequest.frame_number = request.frameNumber;
+    bool converted = convertFromHidl(request.settings, &halRequest.settings);
+    if (!converted) {
+        ALOGE("%s: capture request settings metadata is corrupt!", __FUNCTION__);
+        return Status::INTERNAL_ERROR;
+    }
+
+    hidl_vec<buffer_handle_t*> allBufPtrs;
+    hidl_vec<int> allFences;
+    bool hasInputBuf = (request.inputBuffer.streamId != -1 &&
+            request.inputBuffer.bufferId != 0);
+    size_t numOutputBufs = request.outputBuffers.size();
+    size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
+    status = importRequest(request, allBufPtrs, allFences);
+    if (status != Status::OK) {
+        return status;
+    }
+
+    hidl_vec<camera3_stream_buffer_t> outHalBufs;
+    outHalBufs.resize(numOutputBufs);
+    {
+        Mutex::Autolock _l(mInflightLock);
+        if (hasInputBuf) {
+            auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[numOutputBufs], request.inputBuffer.status,
+                    &mStreamMap[request.inputBuffer.streamId], allFences[numOutputBufs],
+                    &bufCache);
+            halRequest.input_buffer = &bufCache;
+        } else {
+            halRequest.input_buffer = nullptr;
+        }
+
+        halRequest.num_output_buffers = numOutputBufs;
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
+            auto& bufCache = mInflightBuffers[key] = camera3_stream_buffer_t{};
+            convertFromHidl(
+                    allBufPtrs[i], request.outputBuffers[i].status,
+                    &mStreamMap[request.outputBuffers[i].streamId], allFences[i],
+                    &bufCache);
+            outHalBufs[i] = bufCache;
+        }
+        halRequest.output_buffers = outHalBufs.data();
+    }
+
+    ATRACE_ASYNC_BEGIN("frame capture", request.frameNumber);
+    ATRACE_BEGIN("camera3->process_capture_request");
+    status_t ret = mDevice->ops->process_capture_request(mDevice, &halRequest);
+    ATRACE_END();
+    if (ret != OK) {
+        Mutex::Autolock _l(mInflightLock);
+        ALOGE("%s: HAL process_capture_request call failed!", __FUNCTION__);
+
+        cleanupInflightFences(allFences, numBufs);
+        if (hasInputBuf) {
+            auto key = std::make_pair(request.inputBuffer.streamId, request.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            auto key = std::make_pair(request.outputBuffers[i].streamId, request.frameNumber);
+            mInflightBuffers.erase(key);
+        }
+        return Status::INTERNAL_ERROR;
+    }
+
+    return Status::OK;
+}
+
+Return<Status> CameraDeviceSession::flush()  {
+    Status status = initStatus();
+    if (status == Status::OK) {
+        // Flush is always supported on device 3.1 or later
+        status_t ret = mDevice->ops->flush(mDevice);
+        if (ret != OK) {
+            status = Status::INTERNAL_ERROR;
+        }
+    }
+    return status;
+}
+
+Return<void> CameraDeviceSession::close()  {
+    Mutex::Autolock _l(mStateLock);
+    if (!mClosed) {
+        {
+            Mutex::Autolock _l(mInflightLock);
+            if (!mInflightBuffers.empty()) {
+                ALOGE("%s: trying to close while there are still %zu inflight buffers!",
+                        __FUNCTION__, mInflightBuffers.size());
+            }
+        }
+
+        ATRACE_BEGIN("camera3->close");
+        mDevice->common.close(&mDevice->common);
+        ATRACE_END();
+
+        // free all imported buffers
+        for(auto& pair : mCirculatingBuffers) {
+            CirculatingBuffers& buffers = pair.second;
+            for (auto& p2 : buffers) {
+                sHandleImporter.freeBuffer(p2.second);
+            }
+        }
+
+        mClosed = true;
+    }
+    return Void();
+}
+
+/**
+ * Static callback forwarding methods from HAL to instance
+ */
+void CameraDeviceSession::sProcessCaptureResult(
+        const camera3_callback_ops *cb,
+        const camera3_capture_result *hal_result) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+
+    uint32_t frameNumber = hal_result->frame_number;
+    bool hasInputBuf = (hal_result->input_buffer != nullptr);
+    size_t numOutputBufs = hal_result->num_output_buffers;
+    size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
+    Status status = Status::OK;
+    {
+        Mutex::Autolock _l(d->mInflightLock);
+        if (hasInputBuf) {
+            int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
+            // validate if buffer is inflight
+            auto key = std::make_pair(streamId, frameNumber);
+            if (d->mInflightBuffers.count(key) != 1) {
+                ALOGE("%s: input buffer for stream %d frame %d is not inflight!",
+                        __FUNCTION__, streamId, frameNumber);
+                return;
+            }
+        }
+
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
+            // validate if buffer is inflight
+            auto key = std::make_pair(streamId, frameNumber);
+            if (d->mInflightBuffers.count(key) != 1) {
+                ALOGE("%s: output buffer for stream %d frame %d is not inflight!",
+                        __FUNCTION__, streamId, frameNumber);
+                return;
+            }
+        }
+    }
+    // We don't need to validate/import fences here since we will be passing them to camera service
+    // within the scope of this function
+
+    CaptureResult result;
+    hidl_vec<native_handle_t*> releaseFences;
+    releaseFences.resize(numBufs);
+    result.frameNumber = frameNumber;
+    result.partialResult = hal_result->partial_result;
+    convertToHidl(hal_result->result, &result.result);
+    if (hasInputBuf) {
+        result.inputBuffer.streamId =
+                static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
+        result.inputBuffer.buffer = nullptr;
+        result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
+        // skip acquire fence since it's no use to camera service
+        if (hal_result->input_buffer->release_fence != -1) {
+            releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
+            releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
+            result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
+        } else {
+            releaseFences[numOutputBufs] = nullptr;
+        }
+    } else {
+        result.inputBuffer.streamId = -1;
+    }
+
+    result.outputBuffers.resize(numOutputBufs);
+    for (size_t i = 0; i < numOutputBufs; i++) {
+        result.outputBuffers[i].streamId =
+                static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
+        result.outputBuffers[i].buffer = nullptr;
+        result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
+        // skip acquire fence since it's of no use to camera service
+        if (hal_result->output_buffers[i].release_fence != -1) {
+            releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
+            releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
+            result.outputBuffers[i].releaseFence = releaseFences[i];
+        } else {
+            releaseFences[i] = nullptr;
+        }
+    }
+
+    // Free inflight record/fences.
+    // Do this before call back to camera service because camera service might jump to
+    // configure_streams right after the processCaptureResult call so we need to finish
+    // updating inflight queues first
+    {
+        Mutex::Autolock _l(d->mInflightLock);
+        if (hasInputBuf) {
+            int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
+            auto key = std::make_pair(streamId, frameNumber);
+            // TODO (b/34169301): currently HAL closed the fence
+            //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
+            d->mInflightBuffers.erase(key);
+        }
+
+        for (size_t i = 0; i < numOutputBufs; i++) {
+            int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
+            auto key = std::make_pair(streamId, frameNumber);
+            // TODO (b/34169301): currently HAL closed the fence
+            //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
+            d->mInflightBuffers.erase(key);
+        }
+
+        if (d->mInflightBuffers.empty()) {
+            ALOGV("%s: inflight buffer queue is now empty!", __FUNCTION__);
+        }
+    }
+
+    d->mCallback->processCaptureResult(result);
+
+    for (size_t i = 0; i < releaseFences.size(); i++) {
+        // We don't close the FD here as HAL needs to signal it later.
+        native_handle_delete(releaseFences[i]);
+    }
+}
+
+void CameraDeviceSession::sNotify(
+        const camera3_callback_ops *cb,
+        const camera3_notify_msg *msg) {
+    CameraDeviceSession *d =
+            const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
+    NotifyMsg hidlMsg;
+    convertToHidl(msg, &hidlMsg);
+    if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
+            hidlMsg.msg.error.errorStreamId != -1) {
+        if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
+            ALOGE("%s: unknown stream ID %d reports an error!",
+                    __FUNCTION__, hidlMsg.msg.error.errorStreamId);
+        }
+        return;
+    }
+    d->mCallback->notify(hidlMsg);
+}
+
+} // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
new file mode 100644
index 0000000..ca9d24d
--- /dev/null
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
+
+#include <unordered_map>
+#include "hardware/camera_common.h"
+#include "hardware/camera3.h"
+#include "utils/Mutex.h"
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.2/ICameraDeviceSession.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include <include/convert.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_2::StreamConfiguration;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+/**
+ * Function pointer types with C calling convention to
+ * use for HAL callback functions.
+ */
+extern "C" {
+    typedef void (callbacks_process_capture_result_t)(
+        const struct camera3_callback_ops *,
+        const camera3_capture_result_t *);
+
+    typedef void (callbacks_notify_t)(
+        const struct camera3_callback_ops *,
+        const camera3_notify_msg_t *);
+}
+
+struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callback_ops  {
+
+    CameraDeviceSession(camera3_device_t*, const sp<ICameraDeviceCallback>&);
+    ~CameraDeviceSession();
+    // Call by CameraDevice to dump active device states
+    void dumpState(const native_handle_t* fd);
+    // Caller must use this method to check if CameraDeviceSession ctor failed
+    bool isInitFailed() { return mInitFail; }
+    // Used by CameraDevice to signal external camera disconnected
+    void disconnect();
+    bool isClosed();
+
+    // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
+    Return<void> constructDefaultRequestSettings(RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
+    Return<void> configureStreams(const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
+    Return<Status> processCaptureRequest(const CaptureRequest& request) override;
+    Return<Status> flush() override;
+    Return<void> close() override;
+
+private:
+    // protecting mClosed/mDisconnected/mInitFail
+    mutable Mutex mStateLock;
+    // device is closed either
+    //    - closed by user
+    //    - init failed
+    //    - camera disconnected
+    bool mClosed = false;
+
+    // Set by CameraDevice (when external camera is disconnected)
+    bool mDisconnected = false;
+
+    camera3_device_t* mDevice;
+    const sp<ICameraDeviceCallback> mCallback;
+    // Stream ID -> Camera3Stream cache
+    std::map<int, Camera3Stream> mStreamMap;
+
+    mutable Mutex mInflightLock; // protecting mInflightBuffers and mCirculatingBuffers
+    // (streamID, frameNumber) -> inflight buffer cache
+    std::map<std::pair<int, uint32_t>, camera3_stream_buffer_t>  mInflightBuffers;
+
+    // buffers currently ciculating between HAL and camera service
+    // key: bufferId sent via HIDL interface
+    // value: imported buffer_handle_t
+    // Buffer will be imported during process_capture_request and will be freed
+    // when the its stream is deleted or camera device session is closed
+    typedef std::unordered_map<uint64_t, buffer_handle_t> CirculatingBuffers;
+    // Stream ID -> circulating buffers map
+    std::map<int, CirculatingBuffers> mCirculatingBuffers;
+
+    bool mInitFail;
+    bool initialize();
+
+    Status initStatus() const;
+
+    // Validate and import request's input buffer and acquire fence
+    Status importRequest(
+            const CaptureRequest& request,
+            hidl_vec<buffer_handle_t*>& allBufPtrs,
+            hidl_vec<int>& allFences);
+
+    static void cleanupInflightFences(
+            hidl_vec<int>& allFences, size_t numFences);
+
+    /**
+     * Static callback forwarding methods from HAL to instance
+     */
+    static callbacks_process_capture_result_t sProcessCaptureResult;
+    static callbacks_notify_t sNotify;
+};
+
+}  // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
new file mode 100644
index 0000000..35676df
--- /dev/null
+++ b/camera/device/3.2/default/convert.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.camera.device@3.2-convert-impl"
+#include <android/log.h>
+
+#include "include/convert.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+using ::android::hardware::graphics::common::V1_0::Dataspace;
+using ::android::hardware::graphics::common::V1_0::PixelFormat;
+using ::android::hardware::camera::device::V3_2::ConsumerUsageFlags;
+using ::android::hardware::camera::device::V3_2::ProducerUsageFlags;
+
+bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst) {
+    if (src.size() == 0) {
+        // Special case for null metadata
+        *dst = nullptr;
+        return true;
+    }
+
+    const uint8_t* data = src.data();
+    // sanity check the size of CameraMetadata match underlying camera_metadata_t
+    if (get_camera_metadata_size((camera_metadata_t*)data) != src.size()) {
+        ALOGE("%s: input CameraMetadata is corrupt!", __FUNCTION__);
+        return false;
+    }
+    *dst = (camera_metadata_t*) data;
+    return true;
+}
+
+// Note: existing data in dst will be gone. Caller still owns the memory of src
+void convertToHidl(const camera_metadata_t *src, CameraMetadata* dst) {
+    if (src == nullptr) {
+        return;
+    }
+    size_t size = get_camera_metadata_size(src);
+    dst->setToExternal((uint8_t *) src, size);
+    return;
+}
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst) {
+    dst->mId = src.id;
+    dst->stream_type = (int) src.streamType;
+    dst->width = src.width;
+    dst->height = src.height;
+    dst->format = (int) src.format;
+    dst->data_space = (android_dataspace_t) src.dataSpace;
+    dst->rotation = (int) src.rotation;
+    dst->usage = (uint32_t) src.usage;
+    // Fields to be filled by HAL (max_buffers, priv) are initialized to 0
+    dst->max_buffers = 0;
+    dst->priv = 0;
+    return;
+}
+
+void convertToHidl(const Camera3Stream* src, HalStream* dst) {
+    dst->id = src->mId;
+    dst->overrideFormat = (PixelFormat) src->format;
+    dst->maxBuffers = src->max_buffers;
+    if (src->stream_type == CAMERA3_STREAM_OUTPUT) {
+        dst->consumerUsage = (ConsumerUsageFlags) 0;
+        dst->producerUsage = (ProducerUsageFlags) src->usage;
+    } else if (src->stream_type == CAMERA3_STREAM_INPUT) {
+        dst->producerUsage = (ProducerUsageFlags) 0;
+        dst->consumerUsage = (ConsumerUsageFlags) src->usage;
+    } else {
+        //Should not reach here per current HIDL spec, but we might end up adding
+        // bi-directional stream to HIDL.
+        ALOGW("%s: Stream type %d is not currently supported!",
+                __FUNCTION__, src->stream_type);
+    }
+}
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst) {
+    dst->streams.resize(src.num_streams);
+    for (uint32_t i = 0; i < src.num_streams; i++) {
+        convertToHidl(static_cast<Camera3Stream*>(src.streams[i]), &dst->streams[i]);
+    }
+    return;
+}
+
+void convertFromHidl(
+        buffer_handle_t* bufPtr, BufferStatus status, camera3_stream_t* stream, int acquireFence,
+        camera3_stream_buffer_t* dst) {
+    dst->stream = stream;
+    dst->buffer = bufPtr;
+    dst->status = (int) status;
+    dst->acquire_fence = acquireFence;
+    dst->release_fence = -1; // meant for HAL to fill in
+}
+
+void convertToHidl(const camera3_notify_msg* src, NotifyMsg* dst) {
+    dst->type = (MsgType) src->type;
+    switch (src->type) {
+        case CAMERA3_MSG_ERROR:
+            {
+                // The camera3_stream_t* must be the same as what wrapper HAL passed to conventional
+                // HAL, or the ID lookup will return garbage. Caller should validate the ID here is
+                // indeed one of active stream IDs
+                Camera3Stream* stream = static_cast<Camera3Stream*>(
+                        src->message.error.error_stream);
+                dst->msg.error.frameNumber = src->message.error.frame_number;
+                dst->msg.error.errorStreamId = (stream != nullptr) ? stream->mId : -1;
+                dst->msg.error.errorCode = (ErrorCode) src->message.error.error_code;
+            }
+            break;
+        case CAMERA3_MSG_SHUTTER:
+            dst->msg.shutter.frameNumber = src->message.shutter.frame_number;
+            dst->msg.shutter.timestamp = src->message.shutter.timestamp;
+            break;
+        default:
+            ALOGE("%s: HIDL type converion failed. Unknown msg type 0x%x",
+                    __FUNCTION__, src->type);
+    }
+    return;
+}
+
+}  // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.2/default/include/convert.h b/camera/device/3.2/default/include/convert.h
new file mode 100644
index 0000000..96891f0
--- /dev/null
+++ b/camera/device/3.2/default/include/convert.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_CAMERA_DEVICE_V3_2_DEFAULT_INCLUDE_CONVERT_H_
+
+#define HARDWARE_INTERFACES_CAMERA_DEVICE_V3_2_DEFAULT_INCLUDE_CONVERT_H_
+
+#include <set>
+
+
+#include <android/hardware/graphics/common/1.0/types.h>
+#include <android/hardware/camera/device/3.2/types.h>
+#include "hardware/camera3.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_2 {
+namespace implementation {
+
+// The camera3_stream_t sent to conventional HAL. Added mId fields to enable stream ID lookup
+// fromt a downcasted camera3_stream
+struct Camera3Stream : public camera3_stream {
+    int mId;
+};
+
+// *dst will point to the data owned by src, but src still owns the data after this call returns.
+bool convertFromHidl(const CameraMetadata &src, const camera_metadata_t** dst);
+void convertToHidl(const camera_metadata_t* src, CameraMetadata* dst);
+
+void convertFromHidl(const Stream &src, Camera3Stream* dst);
+void convertToHidl(const Camera3Stream* src, HalStream* dst);
+
+void convertFromHidl(
+        buffer_handle_t*, BufferStatus, camera3_stream_t*, int acquireFence, // inputs
+        camera3_stream_buffer_t* dst);
+
+void convertToHidl(const camera3_stream_configuration_t& src, HalStreamConfiguration* dst);
+
+// The camera3_stream_t* in src must be the same as what wrapper HAL passed to conventional
+// HAL, or the ID lookup will return garbage. Caller should validate the ID in ErrorMsg is
+// indeed one of active stream IDs
+void convertToHidl(const camera3_notify_msg* src, NotifyMsg* dst);
+
+}  // namespace implementation
+}  // namespace V3_2
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_CAMERA_DEVICE_V3_2_DEFAULT_INCLUDE_CONVERT_H_
diff --git a/camera/device/3.2/types.hal b/camera/device/3.2/types.hal
new file mode 100644
index 0000000..c07a670
--- /dev/null
+++ b/camera/device/3.2/types.hal
@@ -0,0 +1,934 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.2;
+
+import android.hardware.graphics.allocator@2.0::types;
+import android.hardware.graphics.common@1.0::types;
+
+typedef vec<uint8_t> CameraMetadata;
+typedef bitfield<ProducerUsage> ProducerUsageFlags;
+typedef bitfield<ConsumerUsage> ConsumerUsageFlags;
+typedef bitfield<Dataspace> DataspaceFlags;
+
+/**
+ * StreamType:
+ *
+ * The type of the camera stream, which defines whether the camera HAL device is
+ * the producer or the consumer for that stream, and how the buffers of the
+ * stream relate to the other streams.
+ */
+enum StreamType : uint32_t {
+    /**
+     * This stream is an output stream; the camera HAL device must fill buffers
+     * from this stream with newly captured or reprocessed image data.
+     */
+    OUTPUT = 0,
+
+    /**
+     * This stream is an input stream; the camera HAL device must read buffers
+     * from this stream and send them through the camera processing pipeline,
+     * as if the buffer was a newly captured image from the imager.
+     *
+     * The pixel format for input stream can be any format reported by
+     * android.scaler.availableInputOutputFormatsMap. The pixel format of the
+     * output stream that is used to produce the reprocessing data may be any
+     * format reported by android.scaler.availableStreamConfigurations. The
+     * supported input/output stream combinations depends the camera device
+     * capabilities, see android.scaler.availableInputOutputFormatsMap for
+     * stream map details.
+     *
+     * This kind of stream is generally used to reprocess data into higher
+     * quality images (that otherwise would cause a frame rate performance
+     * loss), or to do off-line reprocessing.
+     *
+     * The typical use cases are OPAQUE (typically ZSL) and YUV reprocessing,
+     * see S8.2, S8.3 and S10 for more details.
+     */
+    INPUT = 1
+
+};
+
+/**
+ * StreamRotation:
+ *
+ * The required counterclockwise rotation of camera stream.
+ */
+enum StreamRotation : uint32_t  {
+    /* No rotation */
+    ROTATION_0 = 0,
+
+    /* Rotate by 90 degree counterclockwise */
+    ROTATION_90 = 1,
+
+    /* Rotate by 180 degree counterclockwise */
+    ROTATION_180 = 2,
+
+    /* Rotate by 270 degree counterclockwise */
+    ROTATION_270 = 3
+
+};
+
+/**
+ * StreamConfigurationMode:
+ *
+ * This defines the general operation mode for the HAL (for a given stream
+ * configuration) where modes besides NORMAL have different semantics, and
+ * usually limit the generality of the API in exchange for higher performance in
+ * some particular area.
+ */
+enum StreamConfigurationMode : uint32_t {
+    /**
+     * Normal stream configuration operation mode. This is the default camera
+     * operation mode, where all semantics of HAL APIs and metadata controls
+     * apply.
+     */
+    NORMAL_MODE = 0,
+
+    /**
+     * Special constrained high speed operation mode for devices that can not
+     * support high speed output in NORMAL mode. All streams in this
+     * configuration are operating at high speed mode and have different
+     * characteristics and limitations to achieve high speed output. The NORMAL
+     * mode can still be used for high speed output if the HAL can support high
+     * speed output while satisfying all the semantics of HAL APIs and metadata
+     * controls. It is recommended for the HAL to support high speed output in
+     * NORMAL mode (by advertising the high speed FPS ranges in
+     * android.control.aeAvailableTargetFpsRanges) if possible.
+     *
+     * This mode has below limitations/requirements:
+     *
+     *   1. The HAL must support up to 2 streams with sizes reported by
+     *      android.control.availableHighSpeedVideoConfigurations.
+     *   2. In this mode, the HAL is expected to output up to 120fps or
+     *      higher. This mode must support the targeted FPS range and size
+     *      configurations reported by
+     *      android.control.availableHighSpeedVideoConfigurations.
+     *   3. The HAL must support IMPLEMENTATION_DEFINED output
+     *      stream format.
+     *   4. To achieve efficient high speed streaming, the HAL may have to
+     *      aggregate multiple frames together and send to camera device for
+     *      processing where the request controls are same for all the frames in
+     *      this batch (batch mode). The HAL must support max batch size and the
+     *      max batch size requirements defined by
+     *      android.control.availableHighSpeedVideoConfigurations.
+     *   5. In this mode, the HAL must override aeMode, awbMode, and afMode to
+     *      ON, ON, and CONTINUOUS_VIDEO, respectively. All post-processing
+     *      block mode controls must be overridden to be FAST. Therefore, no
+     *      manual control of capture and post-processing parameters is
+     *      possible. All other controls operate the same as when
+     *      android.control.mode == AUTO. This means that all other
+     *      android.control.* fields must continue to work, such as
+     *
+     *      android.control.aeTargetFpsRange
+     *      android.control.aeExposureCompensation
+     *      android.control.aeLock
+     *      android.control.awbLock
+     *      android.control.effectMode
+     *      android.control.aeRegions
+     *      android.control.afRegions
+     *      android.control.awbRegions
+     *      android.control.afTrigger
+     *      android.control.aePrecaptureTrigger
+     *
+     *      Outside of android.control.*, the following controls must work:
+     *
+     *      android.flash.mode (TORCH mode only, automatic flash for still
+     *          capture must not work since aeMode is ON)
+     *      android.lens.opticalStabilizationMode (if it is supported)
+     *      android.scaler.cropRegion
+     *      android.statistics.faceDetectMode (if it is supported)
+     *
+     * For more details about high speed stream requirements, see
+     * android.control.availableHighSpeedVideoConfigurations and
+     * CONSTRAINED_HIGH_SPEED_VIDEO capability defined in
+     * android.request.availableCapabilities.
+     *
+     * This mode only needs to be supported by HALs that include
+     * CONSTRAINED_HIGH_SPEED_VIDEO in the android.request.availableCapabilities
+     * static metadata.
+     */
+    CONSTRAINED_HIGH_SPEED_MODE = 1
+
+};
+
+/**
+ * Stream:
+ *
+ * A descriptor for a single camera input or output stream. A stream is defined
+ * 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.
+ *
+ * If a configureStreams() call returns a non-fatal error, all active streams
+ * remain valid as if configureStreams() had not been called.
+ *
+ */
+struct Stream {
+    /**
+     * Stream ID - a nonnegative integer identifier for a stream.
+     *
+     * The identical stream ID must reference the same stream, with the same
+     * width/height/format, across consecutive calls to configureStreams.
+     *
+     * If previously-used stream ID is not used in a new call to
+     * configureStreams, then that stream is no longer active. Such a stream ID
+     * may be reused in a future configureStreams with a new
+     * width/height/format.
+     *
+     */
+    int32_t id;
+
+    /**
+     * The type of the stream (input vs output, etc).
+     */
+    StreamType streamType;
+
+    /**
+     * The width in pixels of the buffers in this stream
+     */
+    uint32_t width;
+
+    /**
+     * The height in pixels of the buffers in this stream
+     */
+    uint32_t height;
+
+    /**
+     * The pixel format for the buffers in this stream.
+     *
+     * If IMPLEMENTATION_DEFINED is used, then the platform
+     * gralloc module must select a format based on the usage flags provided by
+     * the camera device and the other endpoint of the stream.
+     *
+     */
+    android.hardware.graphics.common@1.0::PixelFormat format;
+
+    /**
+     * The gralloc usage flags for this stream, as needed by the consumer of
+     * the stream.
+     *
+     * The usage flags from the producer and the consumer must be combined
+     * together and then passed to the platform gralloc HAL module for
+     * allocating the gralloc buffers for each stream.
+     *
+     * The HAL may use these consumer flags to decide stream configuration. For
+     * streamType INPUT, the value of this field is always 0. For all streams
+     * passed via configureStreams(), the HAL must set its own
+     * additional usage flags in its output HalStreamConfiguration.
+     */
+    ConsumerUsageFlags usage;
+
+    /**
+     * A field that describes the contents of the buffer. The format and buffer
+     * dimensions define the memory layout and structure of the stream buffers,
+     * while dataSpace defines the meaning of the data within the buffer.
+     *
+     * For most formats, dataSpace defines the color space of the image data.
+     * In addition, for some formats, dataSpace indicates whether image- or
+     * depth-based data is requested. See
+     * android.hardware.graphics.common@1.0::types for details of formats and
+     * valid dataSpace values for each format.
+     *
+     * The HAL must use this dataSpace to configure the stream to the correct
+     * colorspace, or to select between color and depth outputs if
+     * supported. The dataspace values are set using the V0 dataspace
+     * definitions.
+     */
+    DataspaceFlags dataSpace;
+
+    /**
+     * The required output rotation of the stream.
+     *
+     * This must be inspected by HAL along with stream width and height. For
+     * example, if the rotation is 90 degree and the stream width and height is
+     * 720 and 1280 respectively, camera service must supply buffers of size
+     * 720x1280, and HAL must capture a 1280x720 image and rotate the image by
+     * 90 degree counterclockwise. The rotation field must be ignored when the
+     * stream type is input.
+     *
+     * The HAL must inspect this field during stream configuration and return
+     * IllegalArgument if HAL cannot perform such rotation. HAL must always
+     * support ROTATION_0, so a configureStreams() call must not fail for
+     * unsupported rotation if rotation field of all streams is ROTATION_0.
+     *
+     */
+    StreamRotation rotation;
+
+};
+
+/**
+ * StreamConfiguration:
+ *
+ * A structure of stream definitions, used by configureStreams(). This
+ * structure defines all the output streams and the reprocessing input
+ * stream for the current camera use case.
+ */
+struct StreamConfiguration {
+    /**
+     * An array of camera stream pointers, defining the input/output
+     * configuration for the camera HAL device.
+     *
+     * At most one input-capable stream may be defined.
+     * At least one output-capable stream must be defined.
+     */
+    vec<Stream> streams;
+
+    /**
+     * The operation mode of streams in this configuration. The HAL can use this
+     * mode as an indicator to set the stream property (e.g.,
+     * HalStream::maxBuffers) appropriately. For example, if the
+     * configuration is
+     * CONSTRAINED_HIGH_SPEED_MODE, the HAL may
+     * want to set aside more buffers for batch mode operation (see
+     * android.control.availableHighSpeedVideoConfigurations for batch mode
+     * definition).
+     *
+     */
+    StreamConfigurationMode operationMode;
+
+};
+
+/**
+ * HalStream:
+ *
+ * The camera HAL's response to each requested stream configuration.
+ *
+ * The HAL may specify the desired format, maximum buffers, and
+ * usage flags for each stream.
+ *
+ */
+struct HalStream {
+    /**
+     * Stream ID - a nonnegative integer identifier for a stream.
+     *
+     * The ID must be one of the stream IDs passed into configureStreams.
+     */
+    int32_t id;
+
+    /**
+     * An override pixel format for the buffers in this stream.
+     *
+     * The HAL must respect the requested format in Stream unless it is
+     * IMPLEMENTATION_DEFINED, in which case the override format here must be
+     * used by the client instead, for this stream. This allows cross-platform
+     * HALs to use a standard format since IMPLEMENTATION_DEFINED formats often
+     * require device-specific information. In all other cases, the
+     * overrideFormat must match the requested format.
+     *
+     * When HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED is used, then the platform
+     * gralloc module must select a format based on the usage flags provided by
+     * the camera device and the other endpoint of the stream.
+     */
+    android.hardware.graphics.common@1.0::PixelFormat overrideFormat;
+
+    /**
+     * The gralloc usage flags for this stream, as needed by the HAL.
+     *
+     * For output streams, these are the HAL's producer usage flags. For input
+     * streams, these are the HAL's consumer usage flags. The usage flags from
+     * the producer and the consumer must be combined together and then passed
+     * to the platform graphics allocator HAL for allocating the gralloc buffers
+     * for each stream.
+     *
+     * If the stream's type is INPUT, then producerUsage must be 0, and
+     * consumerUsage must be set. For other types, producerUsage must be set,
+     * and consumerUsage must be 0.
+     */
+    ProducerUsageFlags producerUsage;
+    ConsumerUsageFlags consumerUsage;
+
+    /**
+     * The maximum number of buffers the HAL device may need to have dequeued at
+     * the same time. The HAL device may not have more buffers in-flight from
+     * this stream than this value.
+     */
+    uint32_t maxBuffers;
+
+};
+
+/**
+ * HalStreamConfiguration:
+ *
+ * A structure of stream definitions, returned by configureStreams(). This
+ * structure defines the HAL's desired parameters for each stream.
+ *
+ * All streams that were defined in the input to configureStreams() must have a
+ * corresponding entry in this structure when returned by configureStreams().
+ */
+struct HalStreamConfiguration {
+    vec<HalStream> streams;
+};
+
+/**
+ * BufferStatus:
+ *
+ * The current status of a single stream buffer.
+ */
+enum BufferStatus : uint32_t {
+    /**
+     * The buffer is in a normal state, and can be used after waiting on its
+     * sync fence.
+     */
+    OK = 0,
+
+    /**
+     * The buffer does not contain valid data, and the data in it must not be
+     * used. The sync fence must still be waited on before reusing the buffer.
+     */
+    ERROR = 1
+};
+
+/**
+ * StreamBuffer:
+ *
+ * A single buffer from a camera3 stream. It includes a handle to its parent
+ * stream, the handle to the gralloc buffer itself, and sync fences
+ *
+ * The buffer does not specify whether it is to be used for input or output;
+ * that is determined by its parent stream type and how the buffer is passed to
+ * the HAL device.
+ */
+struct StreamBuffer {
+    /**
+     * The ID of the stream this buffer is associated with. -1 indicates an
+     * invalid (empty) StreamBuffer, in which case buffer must also point to
+     * null and bufferId must be 0.
+     */
+    int32_t streamId;
+
+    /**
+     * The unique ID of the buffer within this StreamBuffer. 0 indicates this
+     * StreamBuffer contains no buffer.
+     * For StreamBuffers sent to the HAL in a CaptureRequest, this ID uniquely
+     * identifies a buffer. When a buffer is sent to HAL for the first time,
+     * both bufferId and buffer handle must be filled. HAL must keep track of
+     * the mapping between bufferId and corresponding buffer until the
+     * corresponding stream is removed from stream configuration or until camera
+     * device session is closed. After the first time a buffer is introduced to
+     * HAL, in the future camera service must refer to the same buffer using
+     * only bufferId, and keep the buffer handle null.
+     */
+    uint64_t bufferId;
+
+    /**
+     * The graphics buffer handle to the buffer.
+     *
+     * For StreamBuffers sent to the HAL in a CaptureRequest, if the bufferId
+     * is not seen by the HAL before, this buffer handle is guaranteed to be a
+     * valid handle to a graphics buffer, with dimensions and format matching
+     * that of the stream. If the bufferId has been sent to the HAL before, this
+     * buffer handle must be null and HAL must look up the actual buffer handle
+     * to use from its own bufferId to buffer handle map.
+     *
+     * For StreamBuffers returned in a CaptureResult, this must be null, since
+     * the handle to the buffer is already known to the client (since the client
+     * sent it in the matching CaptureRequest), and the handle can be identified
+     * by the combination of frame number and stream ID.
+     */
+    handle buffer;
+
+    /**
+     * Current state of the buffer. The framework must not pass buffers to the
+     * HAL that are in an error state. In case a buffer could not be filled by
+     * the HAL, it must have its status set to ERROR when returned to the
+     * framework with processCaptureResult().
+     */
+    BufferStatus status;
+
+    /**
+     * The acquire sync fence for this buffer. The HAL must wait on this fence
+     * fd before attempting to read from or write to this buffer.
+     *
+     * In a buffer included in a CaptureRequest, the client may set this to null
+     * to indicate that no waiting is necessary for this buffer.
+     *
+     * When the HAL returns an input or output buffer to the framework with
+     * processCaptureResult(), the acquireFence must be set to null. If the HAL
+     * never waits on the acquireFence due to an error in filling or reading a
+     * buffer, when calling processCaptureResult() the HAL must set the
+     * releaseFence of the buffer to be the acquireFence passed to it by the
+     * client. This allows the client to wait on the fence before reusing the
+     * buffer.
+     */
+    handle acquireFence;
+
+    /**
+     * The release sync fence for this buffer. The HAL must set this to a valid
+     * fence fd when returning the input buffer or output buffers to the client
+     * in a CaptureResult, or set it to null to indicate that no waiting is
+     * required for this buffer.
+     *
+     * The client must set this to be null for all buffers included in a
+     * processCaptureRequest call.
+     *
+     * After signaling the releaseFence for this buffer, the HAL
+     * must not make any further attempts to access this buffer as the
+     * ownership has been fully transferred back to the client.
+     *
+     * If this is null, then the ownership of this buffer is transferred back
+     * immediately upon the call of processCaptureResult.
+     */
+    handle releaseFence;
+
+};
+
+/**
+ * CameraBlob:
+ *
+ * Transport header for camera blob types; generally compressed JPEG buffers in
+ * output streams.
+ *
+ * To capture JPEG images, a stream is created using the pixel format
+ * HAL_PIXEL_FORMAT_BLOB and dataspace HAL_DATASPACE_V0_JFIF. The buffer size
+ * for the stream is calculated by the framework, based on the static metadata
+ * field android.jpeg.maxSize. Since compressed JPEG images are of variable
+ * size, the HAL needs to include the final size of the compressed image using
+ * this structure inside the output stream buffer. The camera blob ID field must
+ * be set to CameraBlobId::JPEG.
+ *
+ * The transport header must be at the end of the JPEG output stream
+ * buffer. That means the jpegBlobId must start at byte[buffer_size -
+ * sizeof(CameraBlob)], where the buffer_size is the size of gralloc
+ * buffer. Any HAL using this transport header must account for it in
+ * android.jpeg.maxSize. The JPEG data itself starts at the beginning of the
+ * buffer and must be blobSize bytes long.
+ */
+enum CameraBlobId : uint16_t {
+    JPEG = 0x00FF,
+};
+
+struct CameraBlob {
+    CameraBlobId blobId;
+
+    uint32_t blobSize;
+};
+
+/**
+ * MsgType:
+ *
+ * Indicates the type of message sent, which specifies which member of the
+ * message union is valid.
+ *
+ */
+enum MsgType : uint32_t {
+    /**
+     * An error has occurred. NotifyMsg::Message::Error contains the
+     * error information.
+     */
+    ERROR = 1,
+
+    /**
+     * The exposure of a given request or processing a reprocess request has
+     * begun. NotifyMsg::Message::Shutter contains the information
+     * the capture.
+     */
+    SHUTTER = 2
+};
+
+/**
+ * Defined error codes for MsgType::ERROR
+ */
+enum ErrorCode : uint32_t {
+    /**
+     * A serious failure occured. No further frames or buffer streams must
+     * be produced by the device. Device must be treated as closed. The
+     * client must reopen the device to use it again. The frameNumber field
+     * is unused.
+     */
+    ERROR_DEVICE = 1,
+
+    /**
+     * An error has occurred in processing a request. No output (metadata or
+     * buffers) must be produced for this request. The frameNumber field
+     * specifies which request has been dropped. Subsequent requests are
+     * unaffected, and the device remains operational.
+     */
+    ERROR_REQUEST = 2,
+
+    /**
+     * An error has occurred in producing an output result metadata buffer
+     * for a request, but output stream buffers for it must still be
+     * available. Subsequent requests are unaffected, and the device remains
+     * operational. The frameNumber field specifies the request for which
+     * result metadata won't be available.
+     */
+    ERROR_RESULT = 3,
+
+    /**
+     * An error has occurred in placing an output buffer into a stream for a
+     * request. The frame metadata and other buffers may still be
+     * available. Subsequent requests are unaffected, and the device remains
+     * operational. The frameNumber field specifies the request for which the
+     * buffer was dropped, and errorStreamId indicates the stream
+     * that dropped the frame.
+     */
+    ERROR_BUFFER = 4,
+};
+
+/**
+ * ErrorMsg:
+ *
+ * Message contents for MsgType::ERROR
+ */
+struct ErrorMsg {
+    /**
+     * Frame number of the request the error applies to. 0 if the frame number
+     * isn't applicable to the error.
+     */
+    uint32_t frameNumber;
+
+    /**
+     * Pointer to the stream that had a failure. -1 if the stream isn't
+     * applicable to the error.
+     */
+    int32_t errorStreamId;
+
+    /**
+     * The code for this error.
+     */
+    ErrorCode errorCode;
+
+};
+
+/**
+ * ShutterMsg:
+ *
+ * Message contents for MsgType::SHUTTER
+ */
+struct ShutterMsg {
+    /**
+     * Frame number of the request that has begun exposure or reprocessing.
+     */
+    uint32_t frameNumber;
+
+    /**
+     * Timestamp for the start of capture. For a reprocess request, this must
+     * be input image's start of capture. This must match the capture result
+     * metadata's sensor exposure start timestamp.
+     */
+    uint64_t timestamp;
+
+};
+
+/**
+ * NotifyMsg:
+ *
+ * The message structure sent to ICameraDevice3Callback::notify()
+ */
+struct NotifyMsg {
+    /**
+     * The message type.
+     */
+    MsgType type;
+
+    union Message {
+        /**
+         * Error message contents. Valid if type is MsgType::ERROR
+         */
+        ErrorMsg error;
+
+        /**
+         * Shutter message contents. Valid if type is MsgType::SHUTTER
+         */
+        ShutterMsg shutter;
+    } msg;
+
+};
+
+/**
+ * RequestTemplate:
+ *
+ * Available template types for
+ * ICameraDevice::constructDefaultRequestSettings()
+ */
+enum RequestTemplate : uint32_t {
+    /**
+     * Standard camera preview operation with 3A on auto.
+     */
+    PREVIEW = 1,
+
+    /**
+     * Standard camera high-quality still capture with 3A and flash on auto.
+     */
+    STILL_CAPTURE = 2,
+
+    /**
+     * Standard video recording plus preview with 3A on auto, torch off.
+     */
+    VIDEO_RECORD = 3,
+
+    /**
+     * High-quality still capture while recording video. Applications typically
+     * include preview, video record, and full-resolution YUV or JPEG streams in
+     * request. Must not cause stuttering on video stream. 3A on auto.
+     */
+    VIDEO_SNAPSHOT = 4,
+
+    /**
+     * Zero-shutter-lag mode. Application typically request preview and
+     * full-resolution data for each frame, and reprocess it to JPEG when a
+     * still image is requested by user. Settings must provide highest-quality
+     * full-resolution images without compromising preview frame rate. 3A on
+     * auto.
+     */
+    ZERO_SHUTTER_LAG = 5,
+
+    /**
+     * A basic template for direct application control of capture
+     * parameters. All automatic control is disabled (auto-exposure, auto-white
+     * balance, auto-focus), and post-processing parameters are set to preview
+     * quality. The manual capture parameters (exposure, sensitivity, etc.)
+     * are set to reasonable defaults, but may be overridden by the
+     * application depending on the intended use case.
+     */
+    MANUAL = 6,
+
+    /**
+     * First value for vendor-defined request templates
+     */
+    VENDOR_TEMPLATE_START = 0x40000000,
+
+};
+
+/**
+ * CaptureRequest:
+ *
+ * A single request for image capture/buffer reprocessing, sent to the Camera
+ * HAL device by the framework in processCaptureRequest().
+ *
+ * The request contains the settings to be used for this capture, and the set of
+ * output buffers to write the resulting image data in. It may optionally
+ * contain an input buffer, in which case the request is for reprocessing that
+ * input buffer instead of capturing a new image with the camera sensor. The
+ * capture is identified by the frameNumber.
+ *
+ * In response, the camera HAL device must send a CaptureResult
+ * structure asynchronously to the framework, using the processCaptureResult()
+ * callback.
+ */
+struct CaptureRequest {
+    /**
+     * The frame number is an incrementing integer set by the framework to
+     * uniquely identify this capture. It needs to be returned in the result
+     * call, and is also used to identify the request in asynchronous
+     * notifications sent to ICameraDevice3Callback::notify().
+     */
+    uint32_t frameNumber;
+
+    /**
+     * The settings buffer contains the capture and processing parameters for
+     * the request. As a special case, an empty settings buffer indicates that
+     * the settings are identical to the most-recently submitted capture
+     * request. A empty buffer cannot be used as the first submitted request
+     * after a configureStreams() call.
+     */
+    CameraMetadata settings;
+
+    /**
+     * The input stream buffer to use for this request, if any.
+     *
+     * An invalid inputBuffer is signified by a null inputBuffer::buffer, in
+     * which case the value of all other members of inputBuffer must be ignored.
+     *
+     * If inputBuffer is invalid, then the request is for a new capture from the
+     * imager. If inputBuffer is valid, the request is for reprocessing the
+     * image contained in inputBuffer, and the HAL must release the inputBuffer
+     * back to the client in a subsequent processCaptureResult call.
+     *
+     * The HAL is required to wait on the acquire sync fence of the input buffer
+     * before accessing it.
+     *
+     */
+    StreamBuffer inputBuffer;
+
+    /**
+     * An array of at least 1 stream buffers, to be filled with image
+     * data from this capture/reprocess. The HAL must wait on the acquire fences
+     * of each stream buffer before writing to them.
+     *
+     * The HAL takes ownership of the handles in outputBuffers; the client
+     * must not access them until they are returned in a CaptureResult.
+     *
+     * Any or all of the buffers included here may be brand new in this
+     * request (having never before seen by the HAL).
+     */
+    vec<StreamBuffer> outputBuffers;
+
+};
+
+/**
+ * CaptureResult:
+ *
+ * The result of a single capture/reprocess by the camera HAL device. This is
+ * sent to the framework asynchronously with processCaptureResult(), in
+ * response to a single capture request sent to the HAL with
+ * processCaptureRequest(). Multiple processCaptureResult() calls may be
+ * performed by the HAL for each request.
+ *
+ * Each call, all with the same frame
+ * number, may contain some subset of the output buffers, and/or the result
+ * metadata.
+ *
+ * The result structure contains the output metadata from this capture, and the
+ * set of output buffers that have been/will be filled for this capture. Each
+ * output buffer may come with a release sync fence that the framework must wait
+ * on before reading, in case the buffer has not yet been filled by the HAL.
+ *
+ * The metadata may be provided multiple times for a single frame number. The
+ * framework must accumulate together the final result set by combining each
+ * partial result together into the total result set.
+ *
+ * If an input buffer is given in a request, the HAL must return it in one of
+ * the processCaptureResult calls, and the call may be to just return the
+ * input buffer, without metadata and output buffers; the sync fences must be
+ * handled the same way they are done for output buffers.
+ *
+ * Performance considerations:
+ *
+ * Applications receive these partial results immediately, so sending partial
+ * results is a highly recommended performance optimization to avoid the total
+ * pipeline latency before sending the results for what is known very early on
+ * in the pipeline.
+ *
+ * A typical use case might be calculating the AF state halfway through the
+ * pipeline; by sending the state back to the framework immediately, we get a
+ * 50% performance increase and perceived responsiveness of the auto-focus.
+ *
+ */
+struct CaptureResult {
+    /**
+     * The frame number is an incrementing integer set by the framework in the
+     * submitted request to uniquely identify this capture. It is also used to
+     * identify the request in asynchronous notifications sent to
+     * ICameraDevice3Callback::notify().
+     */
+    uint32_t frameNumber;
+
+    /**
+     * The result metadata for this capture. This contains information about the
+     * final capture parameters, the state of the capture and post-processing
+     * hardware, the state of the 3A algorithms, if enabled, and the output of
+     * any enabled statistics units.
+     *
+     * If there was an error producing the result metadata, result must be an
+     * empty metadata buffer, and notify() must be called with
+     * ErrorCode::ERROR_RESULT.
+     *
+     * Multiple calls to processCaptureResult() with a given frameNumber
+     * may include (partial) result metadata.
+     *
+     * Partial metadata submitted must not include any metadata key returned
+     * in a previous partial result for a given frame. Each new partial result
+     * for that frame must also set a distinct partialResult value.
+     *
+     * If notify has been called with ErrorCode::ERROR_RESULT, all further
+     * partial results for that frame are ignored by the framework.
+     */
+    CameraMetadata result;
+
+    /**
+     * The completed output stream buffers for this capture.
+     *
+     * They may not yet be filled at the time the HAL calls
+     * processCaptureResult(); the framework must wait on the release sync
+     * fences provided by the HAL before reading the buffers.
+     *
+     * The StreamBuffer::buffer handle must be null for all returned buffers;
+     * the client must cache the handle and look it up via the combination of
+     * frame number and stream ID.
+     *
+     * The number of output buffers returned must be less than or equal to the
+     * matching capture request's count. If this is less than the buffer count
+     * in the capture request, at least one more call to processCaptureResult
+     * with the same frameNumber must be made, to return the remaining output
+     * buffers to the framework. This may only be zero if the structure includes
+     * valid result metadata or an input buffer is returned in this result.
+     *
+     * The HAL must set the stream buffer's release sync fence to a valid sync
+     * fd, or to null if the buffer has already been filled.
+     *
+     * If the HAL encounters an error while processing the buffer, and the
+     * buffer is not filled, the buffer's status field must be set to ERROR. If
+     * the HAL did not wait on the acquire fence before encountering the error,
+     * the acquire fence must be copied into the release fence, to allow the
+     * framework to wait on the fence before reusing the buffer.
+     *
+     * The acquire fence must be set to null for all output buffers.
+     *
+     * This vector may be empty; if so, at least one other processCaptureResult
+     * call must be made (or have been made) by the HAL to provide the filled
+     * output buffers.
+     *
+     * When processCaptureResult is called with a new buffer for a frame,
+     * all previous frames' buffers for that corresponding stream must have been
+     * already delivered (the fences need not have yet been signaled).
+     *
+     * Buffers for a frame may be sent to framework before the corresponding
+     * SHUTTER-notify call is made by the HAL.
+     *
+     * Performance considerations:
+     *
+     * Buffers delivered to the framework are not dispatched to the
+     * application layer until a start of exposure timestamp has been received
+     * via a SHUTTER notify() call. It is highly recommended to
+     * dispatch that call as early as possible.
+     */
+    vec<StreamBuffer> outputBuffers;
+
+    /**
+     * The handle for the input stream buffer for this capture, if any.
+     *
+     * It may not yet be consumed at the time the HAL calls
+     * processCaptureResult(); the framework must wait on the release sync fence
+     * provided by the HAL before reusing the buffer.
+     *
+     * The HAL must handle the sync fences the same way they are done for
+     * outputBuffers.
+     *
+     * Only one input buffer is allowed to be sent per request. Similarly to
+     * output buffers, the ordering of returned input buffers must be
+     * maintained by the HAL.
+     *
+     * Performance considerations:
+     *
+     * The input buffer should be returned as early as possible. If the HAL
+     * supports sync fences, it can call processCaptureResult to hand it back
+     * with sync fences being set appropriately. If the sync fences are not
+     * supported, the buffer can only be returned when it is consumed, which
+     * may take long time; the HAL may choose to copy this input buffer to make
+     * the buffer return sooner.
+     */
+    StreamBuffer inputBuffer;
+
+    /**
+     * In order to take advantage of partial results, the HAL must set the
+     * static metadata android.request.partialResultCount to the number of
+     * partial results it sends for each frame.
+     *
+     * Each new capture result with a partial result must set
+     * this field to a distinct inclusive value between
+     * 1 and android.request.partialResultCount.
+     *
+     * HALs not wishing to take advantage of this feature must not
+     * set an android.request.partialResultCount or partial_result to a value
+     * other than 1.
+     *
+     * This value must be set to 0 when a capture result contains buffers only
+     * and no metadata.
+     */
+    uint32_t partialResult;
+
+};
diff --git a/camera/device/README.md b/camera/device/README.md
new file mode 100644
index 0000000..6e5703a
--- /dev/null
+++ b/camera/device/README.md
@@ -0,0 +1,76 @@
+## Camera Device HAL ##
+---
+
+## Overview: ##
+
+The camera.device HAL interface is used by the Android camera service to operate
+individual camera devices. Instances of camera.device HAL interface can be obtained
+via one of the ICameraProvider::getCameraDeviceInterface_V<N>_x() methods, where N
+is the major version of the camera device interface.
+
+Obtaining the device interface does not turn on the respective camera device;
+each camera device interface has an actual open() method to begin an active
+camera session. Without invoking open(), the interface can be used for querying
+camera static information.
+
+More complete information about the Android camera HAL and subsystem can be found at
+[source.android.com](http://source.android.com/devices/camera/index.html).
+
+## Version history: ##
+
+### ICameraDevice.hal@1.0:
+
+HIDL version of the legacy camera device HAL. Intended as a shim for devices
+needing to use the deprecated pre-HIDL camera device HAL v1.0.
+
+May be used in HIDL passthrough mode for devices upgrading to the Android O
+release; must be used in binderized mode for devices launching in the O release.
+
+It is strongly recommended to not use this interface for new devices, as new
+devices may not use this interface starting with the Android P release, and all
+support for ICameraDevice@1.0 will be removed with the Android R release.
+
+This HAL interface version only allows support at the LEGACY level for the
+android.hardware.camera2 API.
+
+Subsidiary HALs:
+
+#### ICameraDevice1PreviewCallback.hal@1.0:
+
+Callback interface for obtaining, filling, and returning graphics buffers for
+preview operation with the ICameraDevice@1.0 inteface.
+
+#### ICameraDevice1Callback.hal@1.0:
+
+Callback interface for sending events and data buffers from the HAL to the
+camera service.
+
+### ICameraDevice.hal@3.2:
+
+HIDL version of the baseline camera device HAL, required for LIMITED or FULL
+operation through the android.hardware.camera2 API.
+
+The main HAL contains methods for static queries about the device, similar to
+the HALv3-specific sections of the legacy camera module HAL. Simply obtaining an
+instance of the camera device interface does not turn on the camera device.
+
+May be used in passthrough mode for devices upgrading to the Android O release;
+must be used in binderized mode for all new devices launching with Android O or
+later.
+
+The open() method actually opens the camera device for use, returning a Session
+interface for operating the active camera. It takes a Callback interface as an
+argument.
+
+Subsidiary HALs:
+
+#### ICameraDevice3Session.hal@3.2:
+
+Closely matches the features and operation of the pre-HIDL camera device HAL
+v3.2, containing methods for configuring an active camera device and submitting
+capture requests to it.
+
+#### ICameraDevice3Callback.hal@3.2:
+
+Callback interface for sending completed captures and other asynchronous events
+from tehe HAL to the client.
diff --git a/camera/metadata/3.2/Android.bp b/camera/metadata/3.2/Android.bp
new file mode 100644
index 0000000..2625026
--- /dev/null
+++ b/camera/metadata/3.2/Android.bp
@@ -0,0 +1,46 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.camera.metadata@3.2_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.metadata@3.2",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/camera/metadata/3.2/types.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.metadata@3.2_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.metadata@3.2",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/camera/metadata/3.2/types.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.metadata@3.2",
+    generated_sources: ["android.hardware.camera.metadata@3.2_genc++"],
+    generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/camera/metadata/3.2/Android.mk b/camera/metadata/3.2/Android.mk
new file mode 100644
index 0000000..083fb6b
--- /dev/null
+++ b/camera/metadata/3.2/Android.mk
@@ -0,0 +1,2424 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.camera.metadata@3.2-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidBlackLevelLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidBlackLevelLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidBlackLevelLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidColorCorrectionAberrationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidColorCorrectionAberrationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidColorCorrectionAberrationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidColorCorrectionMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidColorCorrectionMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidColorCorrectionMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeAntibandingMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeAntibandingMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeAntibandingMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeLockAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeLockAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeLockAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAePrecaptureTrigger)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAePrecaptureTrigger.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAePrecaptureTrigger
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfTrigger)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfTrigger.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfTrigger
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbLockAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbLockAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbLockAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlCaptureIntent)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlCaptureIntent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlCaptureIntent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlEffectMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlEffectMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlEffectMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlSceneMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlSceneMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlSceneMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlVideoStabilizationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlVideoStabilizationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlVideoStabilizationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDemosaicMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDemosaicMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDemosaicMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDepthDepthIsExclusive)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDepthDepthIsExclusive.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDepthDepthIsExclusive
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidEdgeMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidEdgeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidEdgeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashInfoAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashInfoAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashInfoAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidHotPixelMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidHotPixelMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidHotPixelMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidInfoSupportedHardwareLevel)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidInfoSupportedHardwareLevel.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidInfoSupportedHardwareLevel
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLedAvailableLeds)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLedAvailableLeds.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLedAvailableLeds
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLedTransmit)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLedTransmit.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLedTransmit
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensFacing)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensFacing.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensFacing
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensOpticalStabilizationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensOpticalStabilizationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensOpticalStabilizationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidNoiseReductionMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidNoiseReductionMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidNoiseReductionMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidQuirksPartialResult)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidQuirksPartialResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidQuirksPartialResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestAvailableCapabilities)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestAvailableCapabilities.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestAvailableCapabilities
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestMetadataMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestMetadataMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestMetadataMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestType)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerAvailableFormats)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerAvailableFormats.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerAvailableFormats
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerAvailableStreamConfigurations)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerAvailableStreamConfigurations.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerAvailableStreamConfigurations
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerCroppingType)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerCroppingType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerCroppingType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoColorFilterArrangement)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoColorFilterArrangement.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoColorFilterArrangement
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoLensShadingApplied)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoLensShadingApplied.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoLensShadingApplied
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoTimestampSource)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoTimestampSource.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoTimestampSource
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorReferenceIlluminant1)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorReferenceIlluminant1.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorReferenceIlluminant1
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorTestPatternMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorTestPatternMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorTestPatternMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidShadingMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidShadingMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidShadingMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsFaceDetectMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsFaceDetectMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsFaceDetectMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsHistogramMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsHistogramMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsHistogramMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsHotPixelMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsHotPixelMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsHotPixelMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsLensShadingMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsLensShadingMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsLensShadingMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsSceneFlicker)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsSceneFlicker.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsSceneFlicker
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsSharpnessMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsSharpnessMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsSharpnessMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSyncFrameNumber)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSyncFrameNumber.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSyncFrameNumber
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSyncMaxLatency)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSyncMaxLatency.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSyncMaxLatency
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidTonemapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidTonemapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidTonemapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidTonemapPresetCurve)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidTonemapPresetCurve.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidTonemapPresetCurve
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataSection)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataSection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataSection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataSectionStart)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataSectionStart.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataSectionStart
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataTag)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataTag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataTag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.camera.metadata@3.2-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidBlackLevelLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidBlackLevelLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidBlackLevelLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidColorCorrectionAberrationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidColorCorrectionAberrationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidColorCorrectionAberrationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidColorCorrectionMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidColorCorrectionMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidColorCorrectionMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeAntibandingMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeAntibandingMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeAntibandingMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeLockAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeLockAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeLockAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAePrecaptureTrigger)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAePrecaptureTrigger.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAePrecaptureTrigger
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAeState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAeState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAeState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAfTrigger)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAfTrigger.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAfTrigger
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbLock)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbLock.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbLock
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbLockAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbLockAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbLockAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlAwbState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlAwbState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlAwbState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlCaptureIntent)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlCaptureIntent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlCaptureIntent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlEffectMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlEffectMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlEffectMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlSceneMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlSceneMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlSceneMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidControlVideoStabilizationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidControlVideoStabilizationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidControlVideoStabilizationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDemosaicMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDemosaicMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDemosaicMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidDepthDepthIsExclusive)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidDepthDepthIsExclusive.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidDepthDepthIsExclusive
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidEdgeMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidEdgeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidEdgeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashInfoAvailable)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashInfoAvailable.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashInfoAvailable
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidFlashState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidFlashState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidFlashState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidHotPixelMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidHotPixelMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidHotPixelMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidInfoSupportedHardwareLevel)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidInfoSupportedHardwareLevel.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidInfoSupportedHardwareLevel
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLedAvailableLeds)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLedAvailableLeds.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLedAvailableLeds
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLedTransmit)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLedTransmit.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLedTransmit
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensFacing)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensFacing.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensFacing
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensOpticalStabilizationMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensOpticalStabilizationMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensOpticalStabilizationMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidLensState)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidLensState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidLensState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidNoiseReductionMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidNoiseReductionMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidNoiseReductionMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidQuirksPartialResult)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidQuirksPartialResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidQuirksPartialResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestAvailableCapabilities)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestAvailableCapabilities.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestAvailableCapabilities
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestMetadataMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestMetadataMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestMetadataMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidRequestType)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidRequestType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidRequestType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerAvailableFormats)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerAvailableFormats.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerAvailableFormats
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerAvailableStreamConfigurations)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerAvailableStreamConfigurations.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerAvailableStreamConfigurations
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidScalerCroppingType)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidScalerCroppingType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidScalerCroppingType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoColorFilterArrangement)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoColorFilterArrangement.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoColorFilterArrangement
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoLensShadingApplied)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoLensShadingApplied.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoLensShadingApplied
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorInfoTimestampSource)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorInfoTimestampSource.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorInfoTimestampSource
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorReferenceIlluminant1)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorReferenceIlluminant1.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorReferenceIlluminant1
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSensorTestPatternMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSensorTestPatternMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSensorTestPatternMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidShadingMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidShadingMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidShadingMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsFaceDetectMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsFaceDetectMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsFaceDetectMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsHistogramMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsHistogramMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsHistogramMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsHotPixelMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsHotPixelMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsHotPixelMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsLensShadingMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsLensShadingMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsLensShadingMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsSceneFlicker)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsSceneFlicker.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsSceneFlicker
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidStatisticsSharpnessMapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidStatisticsSharpnessMapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidStatisticsSharpnessMapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSyncFrameNumber)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSyncFrameNumber.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSyncFrameNumber
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidSyncMaxLatency)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidSyncMaxLatency.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidSyncMaxLatency
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidTonemapMode)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidTonemapMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidTonemapMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataEnumAndroidTonemapPresetCurve)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataEnumAndroidTonemapPresetCurve.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataEnumAndroidTonemapPresetCurve
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataSection)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataSection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataSection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataSectionStart)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataSectionStart.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataSectionStart
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CameraMetadataTag)
+#
+GEN := $(intermediates)/android/hardware/camera/metadata/V3_2/CameraMetadataTag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.camera.metadata@3.2::types.CameraMetadataTag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/camera/metadata/3.2/docs.html b/camera/metadata/3.2/docs.html
new file mode 100644
index 0000000..004ecae
--- /dev/null
+++ b/camera/metadata/3.2/docs.html
@@ -0,0 +1,27340 @@
+<!DOCTYPE html>
+<html>
+<!-- Copyright (C) 2012 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.
+-->
+<head>
+  <!-- automatically generated from html.mako. do NOT edit directly -->
+  <meta charset="utf-8" />
+  <title>Android Camera HAL3.4 Properties</title>
+  <style type="text/css">
+     body { background-color: #f7f7f7; font-family: Roboto, sans-serif;}
+     h1 { color: #333333; }
+     h2 { color: #333333; }
+     a:link { color: #258aaf; text-decoration: none}
+     a:hover { color: #459aaf; text-decoration: underline }
+     a:visited { color: #154a5f; text-decoration: none}
+    .section { color: #eeeeee; font-size: 1.5em; font-weight: bold; background-color: #888888; padding: 0.5em 0em 0.5em 0.5em; border-width: thick thin thin thin; border-color: #111111 #777777 #777777 #777777}
+    .kind { color: #eeeeee; font-size: 1.2em; font-weight: bold; padding-left: 1.5em; background-color: #aaaaaa }
+    .entry { background-color: #f0f0f0 }
+    .entry_cont { background-color: #f0f0f0 }
+    .entries_header { background-color: #dddddd; text-align: center}
+
+    /* toc style */
+    .toc_section_header { font-size:1.3em;  }
+    .toc_kind_header { font-size:1.2em;  }
+    .toc_deprecated { text-decoration:line-through; }
+
+    /* table column sizes */
+    table { border-collapse:collapse; table-layout: fixed; width: 100%; word-wrap: break-word }
+    td,th { border: 1px solid; border-color: #aaaaaa; padding-left: 0.5em; padding-right: 0.5em }
+    .th_name { width: 20% }
+    .th_units { width: 10% }
+    .th_tags { width: 5% }
+    .th_details { width: 25% }
+    .th_type { width: 20% }
+    .th_description { width: 20% }
+    .th_range { width: 10% }
+    td { font-size: 0.9em; }
+
+    /* hide the first thead, we need it there only to enforce column sizes */
+    .thead_dummy { visibility: hidden; }
+
+    /* Entry flair */
+    .entry_name { color: #333333; padding-left:1.0em; font-size:1.1em; font-family: monospace; vertical-align:top; }
+    .entry_name_deprecated { text-decoration:line-through; }
+
+    /* Entry type flair */
+    .entry_type_name { font-size:1.1em; color: #669900; font-weight: bold;}
+    .entry_type_name_enum:after { color: #669900; font-weight: bold; content:" (enum)" }
+    .entry_type_visibility { font-weight: bolder; padding-left:1em}
+    .entry_type_synthetic { font-weight: bolder; color: #996600; }
+    .entry_type_hwlevel { font-weight: bolder; color: #000066; }
+    .entry_type_deprecated { font-weight: bolder; color: #4D4D4D; }
+    .entry_type_enum_name { font-family: monospace; font-weight: bolder; }
+    .entry_type_enum_notes:before { content:" - " }
+    .entry_type_enum_notes>p:first-child { display:inline; }
+    .entry_type_enum_value:before { content:" = " }
+    .entry_type_enum_value { font-family: monospace; }
+    .entry ul { margin: 0 0 0 0; list-style-position: inside; padding-left: 0.5em; }
+    .entry ul li { padding: 0 0 0 0; margin: 0 0 0 0;}
+    .entry_range_deprecated { font-weight: bolder; }
+
+    /* Entry tags flair */
+    .entry_tags ul { list-style-type: none; }
+
+    /* Entry details (full docs) flair */
+    .entry_details_header { font-weight: bold; background-color: #dddddd;
+      text-align: center; font-size: 1.1em; margin-left: 0em; margin-right: 0em; }
+
+    /* Entry spacer flair */
+    .entry_spacer { background-color: transparent; border-style: none; height: 0.5em; }
+
+    /* TODO: generate abbr element for each tag link? */
+    /* TODO for each x.y.z try to link it to the entry */
+
+  </style>
+
+  <style>
+
+    {
+      /* broken...
+         supposedly there is a bug in chrome that it lays out tables before
+         it knows its being printed, so the page-break-* styles are ignored
+         */
+        tr { page-break-after: always; page-break-inside: avoid; }
+    }
+
+  </style>
+</head>
+
+
+
+<body>
+  <h1>Android Camera HAL3.2 Properties</h1>
+
+
+  <h2>Table of Contents</h2>
+  <ul class="toc">
+    <li><a href="#tag_index" class="toc_section_header">Tags</a></li>
+    <li>
+      <span class="toc_section_header"><a href="#section_colorCorrection">colorCorrection</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.colorCorrection.mode">android.colorCorrection.mode</a></li>
+            <li
+            ><a href="#controls_android.colorCorrection.transform">android.colorCorrection.transform</a></li>
+            <li
+            ><a href="#controls_android.colorCorrection.gains">android.colorCorrection.gains</a></li>
+            <li
+            ><a href="#controls_android.colorCorrection.aberrationMode">android.colorCorrection.aberrationMode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.colorCorrection.mode">android.colorCorrection.mode</a></li>
+            <li
+            ><a href="#dynamic_android.colorCorrection.transform">android.colorCorrection.transform</a></li>
+            <li
+            ><a href="#dynamic_android.colorCorrection.gains">android.colorCorrection.gains</a></li>
+            <li
+            ><a href="#dynamic_android.colorCorrection.aberrationMode">android.colorCorrection.aberrationMode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.colorCorrection.availableAberrationModes">android.colorCorrection.availableAberrationModes</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_control">control</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.control.aeAntibandingMode">android.control.aeAntibandingMode</a></li>
+            <li
+            ><a href="#controls_android.control.aeExposureCompensation">android.control.aeExposureCompensation</a></li>
+            <li
+            ><a href="#controls_android.control.aeLock">android.control.aeLock</a></li>
+            <li
+            ><a href="#controls_android.control.aeMode">android.control.aeMode</a></li>
+            <li
+            ><a href="#controls_android.control.aeRegions">android.control.aeRegions</a></li>
+            <li
+            ><a href="#controls_android.control.aeTargetFpsRange">android.control.aeTargetFpsRange</a></li>
+            <li
+            ><a href="#controls_android.control.aePrecaptureTrigger">android.control.aePrecaptureTrigger</a></li>
+            <li
+            ><a href="#controls_android.control.afMode">android.control.afMode</a></li>
+            <li
+            ><a href="#controls_android.control.afRegions">android.control.afRegions</a></li>
+            <li
+            ><a href="#controls_android.control.afTrigger">android.control.afTrigger</a></li>
+            <li
+            ><a href="#controls_android.control.awbLock">android.control.awbLock</a></li>
+            <li
+            ><a href="#controls_android.control.awbMode">android.control.awbMode</a></li>
+            <li
+            ><a href="#controls_android.control.awbRegions">android.control.awbRegions</a></li>
+            <li
+            ><a href="#controls_android.control.captureIntent">android.control.captureIntent</a></li>
+            <li
+            ><a href="#controls_android.control.effectMode">android.control.effectMode</a></li>
+            <li
+            ><a href="#controls_android.control.mode">android.control.mode</a></li>
+            <li
+            ><a href="#controls_android.control.sceneMode">android.control.sceneMode</a></li>
+            <li
+            ><a href="#controls_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+            <li
+            ><a href="#controls_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.control.aeAvailableAntibandingModes">android.control.aeAvailableAntibandingModes</a></li>
+            <li
+            ><a href="#static_android.control.aeAvailableModes">android.control.aeAvailableModes</a></li>
+            <li
+            ><a href="#static_android.control.aeAvailableTargetFpsRanges">android.control.aeAvailableTargetFpsRanges</a></li>
+            <li
+            ><a href="#static_android.control.aeCompensationRange">android.control.aeCompensationRange</a></li>
+            <li
+            ><a href="#static_android.control.aeCompensationStep">android.control.aeCompensationStep</a></li>
+            <li
+            ><a href="#static_android.control.afAvailableModes">android.control.afAvailableModes</a></li>
+            <li
+            ><a href="#static_android.control.availableEffects">android.control.availableEffects</a></li>
+            <li
+            ><a href="#static_android.control.availableSceneModes">android.control.availableSceneModes</a></li>
+            <li
+            ><a href="#static_android.control.availableVideoStabilizationModes">android.control.availableVideoStabilizationModes</a></li>
+            <li
+            ><a href="#static_android.control.awbAvailableModes">android.control.awbAvailableModes</a></li>
+            <li
+            ><a href="#static_android.control.maxRegions">android.control.maxRegions</a></li>
+            <li
+            ><a href="#static_android.control.maxRegionsAe">android.control.maxRegionsAe</a></li>
+            <li
+            ><a href="#static_android.control.maxRegionsAwb">android.control.maxRegionsAwb</a></li>
+            <li
+            ><a href="#static_android.control.maxRegionsAf">android.control.maxRegionsAf</a></li>
+            <li
+            ><a href="#static_android.control.sceneModeOverrides">android.control.sceneModeOverrides</a></li>
+            <li
+            ><a href="#static_android.control.availableHighSpeedVideoConfigurations">android.control.availableHighSpeedVideoConfigurations</a></li>
+            <li
+            ><a href="#static_android.control.aeLockAvailable">android.control.aeLockAvailable</a></li>
+            <li
+            ><a href="#static_android.control.awbLockAvailable">android.control.awbLockAvailable</a></li>
+            <li
+            ><a href="#static_android.control.availableModes">android.control.availableModes</a></li>
+            <li
+            ><a href="#static_android.control.postRawSensitivityBoostRange">android.control.postRawSensitivityBoostRange</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.control.aePrecaptureId">android.control.aePrecaptureId</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeAntibandingMode">android.control.aeAntibandingMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeExposureCompensation">android.control.aeExposureCompensation</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeLock">android.control.aeLock</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeMode">android.control.aeMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeRegions">android.control.aeRegions</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeTargetFpsRange">android.control.aeTargetFpsRange</a></li>
+            <li
+            ><a href="#dynamic_android.control.aePrecaptureTrigger">android.control.aePrecaptureTrigger</a></li>
+            <li
+            ><a href="#dynamic_android.control.aeState">android.control.aeState</a></li>
+            <li
+            ><a href="#dynamic_android.control.afMode">android.control.afMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.afRegions">android.control.afRegions</a></li>
+            <li
+            ><a href="#dynamic_android.control.afTrigger">android.control.afTrigger</a></li>
+            <li
+            ><a href="#dynamic_android.control.afState">android.control.afState</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.control.afTriggerId">android.control.afTriggerId</a></li>
+            <li
+            ><a href="#dynamic_android.control.awbLock">android.control.awbLock</a></li>
+            <li
+            ><a href="#dynamic_android.control.awbMode">android.control.awbMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.awbRegions">android.control.awbRegions</a></li>
+            <li
+            ><a href="#dynamic_android.control.captureIntent">android.control.captureIntent</a></li>
+            <li
+            ><a href="#dynamic_android.control.awbState">android.control.awbState</a></li>
+            <li
+            ><a href="#dynamic_android.control.effectMode">android.control.effectMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.mode">android.control.mode</a></li>
+            <li
+            ><a href="#dynamic_android.control.sceneMode">android.control.sceneMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a></li>
+            <li
+            ><a href="#dynamic_android.control.postRawSensitivityBoost">android.control.postRawSensitivityBoost</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_demosaic">demosaic</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.demosaic.mode">android.demosaic.mode</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_edge">edge</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.edge.mode">android.edge.mode</a></li>
+            <li
+            ><a href="#controls_android.edge.strength">android.edge.strength</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.edge.availableEdgeModes">android.edge.availableEdgeModes</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.edge.mode">android.edge.mode</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_flash">flash</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.flash.firingPower">android.flash.firingPower</a></li>
+            <li
+            ><a href="#controls_android.flash.firingTime">android.flash.firingTime</a></li>
+            <li
+            ><a href="#controls_android.flash.mode">android.flash.mode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+
+            <li
+            ><a href="#static_android.flash.info.available">android.flash.info.available</a></li>
+            <li
+            ><a href="#static_android.flash.info.chargeDuration">android.flash.info.chargeDuration</a></li>
+
+            <li
+            ><a href="#static_android.flash.colorTemperature">android.flash.colorTemperature</a></li>
+            <li
+            ><a href="#static_android.flash.maxEnergy">android.flash.maxEnergy</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.flash.firingPower">android.flash.firingPower</a></li>
+            <li
+            ><a href="#dynamic_android.flash.firingTime">android.flash.firingTime</a></li>
+            <li
+            ><a href="#dynamic_android.flash.mode">android.flash.mode</a></li>
+            <li
+            ><a href="#dynamic_android.flash.state">android.flash.state</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_hotPixel">hotPixel</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.hotPixel.mode">android.hotPixel.mode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.hotPixel.availableHotPixelModes">android.hotPixel.availableHotPixelModes</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.hotPixel.mode">android.hotPixel.mode</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_jpeg">jpeg</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.jpeg.gpsLocation">android.jpeg.gpsLocation</a></li>
+            <li
+            ><a href="#controls_android.jpeg.gpsCoordinates">android.jpeg.gpsCoordinates</a></li>
+            <li
+            ><a href="#controls_android.jpeg.gpsProcessingMethod">android.jpeg.gpsProcessingMethod</a></li>
+            <li
+            ><a href="#controls_android.jpeg.gpsTimestamp">android.jpeg.gpsTimestamp</a></li>
+            <li
+            ><a href="#controls_android.jpeg.orientation">android.jpeg.orientation</a></li>
+            <li
+            ><a href="#controls_android.jpeg.quality">android.jpeg.quality</a></li>
+            <li
+            ><a href="#controls_android.jpeg.thumbnailQuality">android.jpeg.thumbnailQuality</a></li>
+            <li
+            ><a href="#controls_android.jpeg.thumbnailSize">android.jpeg.thumbnailSize</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.jpeg.availableThumbnailSizes">android.jpeg.availableThumbnailSizes</a></li>
+            <li
+            ><a href="#static_android.jpeg.maxSize">android.jpeg.maxSize</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.jpeg.gpsLocation">android.jpeg.gpsLocation</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.gpsCoordinates">android.jpeg.gpsCoordinates</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.gpsProcessingMethod">android.jpeg.gpsProcessingMethod</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.gpsTimestamp">android.jpeg.gpsTimestamp</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.orientation">android.jpeg.orientation</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.quality">android.jpeg.quality</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.size">android.jpeg.size</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.thumbnailQuality">android.jpeg.thumbnailQuality</a></li>
+            <li
+            ><a href="#dynamic_android.jpeg.thumbnailSize">android.jpeg.thumbnailSize</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_lens">lens</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.lens.aperture">android.lens.aperture</a></li>
+            <li
+            ><a href="#controls_android.lens.filterDensity">android.lens.filterDensity</a></li>
+            <li
+            ><a href="#controls_android.lens.focalLength">android.lens.focalLength</a></li>
+            <li
+            ><a href="#controls_android.lens.focusDistance">android.lens.focusDistance</a></li>
+            <li
+            ><a href="#controls_android.lens.opticalStabilizationMode">android.lens.opticalStabilizationMode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+
+            <li
+            ><a href="#static_android.lens.info.availableApertures">android.lens.info.availableApertures</a></li>
+            <li
+            ><a href="#static_android.lens.info.availableFilterDensities">android.lens.info.availableFilterDensities</a></li>
+            <li
+            ><a href="#static_android.lens.info.availableFocalLengths">android.lens.info.availableFocalLengths</a></li>
+            <li
+            ><a href="#static_android.lens.info.availableOpticalStabilization">android.lens.info.availableOpticalStabilization</a></li>
+            <li
+            ><a href="#static_android.lens.info.hyperfocalDistance">android.lens.info.hyperfocalDistance</a></li>
+            <li
+            ><a href="#static_android.lens.info.minimumFocusDistance">android.lens.info.minimumFocusDistance</a></li>
+            <li
+            ><a href="#static_android.lens.info.shadingMapSize">android.lens.info.shadingMapSize</a></li>
+            <li
+            ><a href="#static_android.lens.info.focusDistanceCalibration">android.lens.info.focusDistanceCalibration</a></li>
+
+            <li
+            ><a href="#static_android.lens.facing">android.lens.facing</a></li>
+            <li
+            ><a href="#static_android.lens.poseRotation">android.lens.poseRotation</a></li>
+            <li
+            ><a href="#static_android.lens.poseTranslation">android.lens.poseTranslation</a></li>
+            <li
+            ><a href="#static_android.lens.intrinsicCalibration">android.lens.intrinsicCalibration</a></li>
+            <li
+            ><a href="#static_android.lens.radialDistortion">android.lens.radialDistortion</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.lens.aperture">android.lens.aperture</a></li>
+            <li
+            ><a href="#dynamic_android.lens.filterDensity">android.lens.filterDensity</a></li>
+            <li
+            ><a href="#dynamic_android.lens.focalLength">android.lens.focalLength</a></li>
+            <li
+            ><a href="#dynamic_android.lens.focusDistance">android.lens.focusDistance</a></li>
+            <li
+            ><a href="#dynamic_android.lens.focusRange">android.lens.focusRange</a></li>
+            <li
+            ><a href="#dynamic_android.lens.opticalStabilizationMode">android.lens.opticalStabilizationMode</a></li>
+            <li
+            ><a href="#dynamic_android.lens.state">android.lens.state</a></li>
+            <li
+            ><a href="#dynamic_android.lens.poseRotation">android.lens.poseRotation</a></li>
+            <li
+            ><a href="#dynamic_android.lens.poseTranslation">android.lens.poseTranslation</a></li>
+            <li
+            ><a href="#dynamic_android.lens.intrinsicCalibration">android.lens.intrinsicCalibration</a></li>
+            <li
+            ><a href="#dynamic_android.lens.radialDistortion">android.lens.radialDistortion</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_noiseReduction">noiseReduction</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.noiseReduction.mode">android.noiseReduction.mode</a></li>
+            <li
+            ><a href="#controls_android.noiseReduction.strength">android.noiseReduction.strength</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.noiseReduction.availableNoiseReductionModes</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.noiseReduction.mode">android.noiseReduction.mode</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_quirks">quirks</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.quirks.meteringCropRegion">android.quirks.meteringCropRegion</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.quirks.triggerAfWithAuto">android.quirks.triggerAfWithAuto</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.quirks.useZslFormat">android.quirks.useZslFormat</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.quirks.usePartialResult">android.quirks.usePartialResult</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.quirks.partialResult">android.quirks.partialResult</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_request">request</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#controls_android.request.frameCount">android.request.frameCount</a></li>
+            <li
+            ><a href="#controls_android.request.id">android.request.id</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#controls_android.request.inputStreams">android.request.inputStreams</a></li>
+            <li
+            ><a href="#controls_android.request.metadataMode">android.request.metadataMode</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#controls_android.request.outputStreams">android.request.outputStreams</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#controls_android.request.type">android.request.type</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.request.maxNumOutputStreams">android.request.maxNumOutputStreams</a></li>
+            <li
+            ><a href="#static_android.request.maxNumOutputRaw">android.request.maxNumOutputRaw</a></li>
+            <li
+            ><a href="#static_android.request.maxNumOutputProc">android.request.maxNumOutputProc</a></li>
+            <li
+            ><a href="#static_android.request.maxNumOutputProcStalling">android.request.maxNumOutputProcStalling</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.request.maxNumReprocessStreams">android.request.maxNumReprocessStreams</a></li>
+            <li
+            ><a href="#static_android.request.maxNumInputStreams">android.request.maxNumInputStreams</a></li>
+            <li
+            ><a href="#static_android.request.pipelineMaxDepth">android.request.pipelineMaxDepth</a></li>
+            <li
+            ><a href="#static_android.request.partialResultCount">android.request.partialResultCount</a></li>
+            <li
+            ><a href="#static_android.request.availableCapabilities">android.request.availableCapabilities</a></li>
+            <li
+            ><a href="#static_android.request.availableRequestKeys">android.request.availableRequestKeys</a></li>
+            <li
+            ><a href="#static_android.request.availableResultKeys">android.request.availableResultKeys</a></li>
+            <li
+            ><a href="#static_android.request.availableCharacteristicsKeys">android.request.availableCharacteristicsKeys</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.request.frameCount">android.request.frameCount</a></li>
+            <li
+            ><a href="#dynamic_android.request.id">android.request.id</a></li>
+            <li
+            ><a href="#dynamic_android.request.metadataMode">android.request.metadataMode</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.request.outputStreams">android.request.outputStreams</a></li>
+            <li
+            ><a href="#dynamic_android.request.pipelineDepth">android.request.pipelineDepth</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_scaler">scaler</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.scaler.cropRegion">android.scaler.cropRegion</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableFormats">android.scaler.availableFormats</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableJpegMinDurations">android.scaler.availableJpegMinDurations</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableJpegSizes">android.scaler.availableJpegSizes</a></li>
+            <li
+            ><a href="#static_android.scaler.availableMaxDigitalZoom">android.scaler.availableMaxDigitalZoom</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableProcessedMinDurations">android.scaler.availableProcessedMinDurations</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableProcessedSizes">android.scaler.availableProcessedSizes</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableRawMinDurations">android.scaler.availableRawMinDurations</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#static_android.scaler.availableRawSizes">android.scaler.availableRawSizes</a></li>
+            <li
+            ><a href="#static_android.scaler.availableInputOutputFormatsMap">android.scaler.availableInputOutputFormatsMap</a></li>
+            <li
+            ><a href="#static_android.scaler.availableStreamConfigurations">android.scaler.availableStreamConfigurations</a></li>
+            <li
+            ><a href="#static_android.scaler.availableMinFrameDurations">android.scaler.availableMinFrameDurations</a></li>
+            <li
+            ><a href="#static_android.scaler.availableStallDurations">android.scaler.availableStallDurations</a></li>
+            <li
+            ><a href="#static_android.scaler.streamConfigurationMap">android.scaler.streamConfigurationMap</a></li>
+            <li
+            ><a href="#static_android.scaler.croppingType">android.scaler.croppingType</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.scaler.cropRegion">android.scaler.cropRegion</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_sensor">sensor</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.sensor.exposureTime">android.sensor.exposureTime</a></li>
+            <li
+            ><a href="#controls_android.sensor.frameDuration">android.sensor.frameDuration</a></li>
+            <li
+            ><a href="#controls_android.sensor.sensitivity">android.sensor.sensitivity</a></li>
+            <li
+            ><a href="#controls_android.sensor.testPatternData">android.sensor.testPatternData</a></li>
+            <li
+            ><a href="#controls_android.sensor.testPatternMode">android.sensor.testPatternMode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+
+            <li
+            ><a href="#static_android.sensor.info.activeArraySize">android.sensor.info.activeArraySize</a></li>
+            <li
+            ><a href="#static_android.sensor.info.sensitivityRange">android.sensor.info.sensitivityRange</a></li>
+            <li
+            ><a href="#static_android.sensor.info.colorFilterArrangement">android.sensor.info.colorFilterArrangement</a></li>
+            <li
+            ><a href="#static_android.sensor.info.exposureTimeRange">android.sensor.info.exposureTimeRange</a></li>
+            <li
+            ><a href="#static_android.sensor.info.maxFrameDuration">android.sensor.info.maxFrameDuration</a></li>
+            <li
+            ><a href="#static_android.sensor.info.physicalSize">android.sensor.info.physicalSize</a></li>
+            <li
+            ><a href="#static_android.sensor.info.pixelArraySize">android.sensor.info.pixelArraySize</a></li>
+            <li
+            ><a href="#static_android.sensor.info.whiteLevel">android.sensor.info.whiteLevel</a></li>
+            <li
+            ><a href="#static_android.sensor.info.timestampSource">android.sensor.info.timestampSource</a></li>
+            <li
+            ><a href="#static_android.sensor.info.lensShadingApplied">android.sensor.info.lensShadingApplied</a></li>
+            <li
+            ><a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.sensor.info.preCorrectionActiveArraySize</a></li>
+
+            <li
+            ><a href="#static_android.sensor.referenceIlluminant1">android.sensor.referenceIlluminant1</a></li>
+            <li
+            ><a href="#static_android.sensor.referenceIlluminant2">android.sensor.referenceIlluminant2</a></li>
+            <li
+            ><a href="#static_android.sensor.calibrationTransform1">android.sensor.calibrationTransform1</a></li>
+            <li
+            ><a href="#static_android.sensor.calibrationTransform2">android.sensor.calibrationTransform2</a></li>
+            <li
+            ><a href="#static_android.sensor.colorTransform1">android.sensor.colorTransform1</a></li>
+            <li
+            ><a href="#static_android.sensor.colorTransform2">android.sensor.colorTransform2</a></li>
+            <li
+            ><a href="#static_android.sensor.forwardMatrix1">android.sensor.forwardMatrix1</a></li>
+            <li
+            ><a href="#static_android.sensor.forwardMatrix2">android.sensor.forwardMatrix2</a></li>
+            <li
+            ><a href="#static_android.sensor.baseGainFactor">android.sensor.baseGainFactor</a></li>
+            <li
+            ><a href="#static_android.sensor.blackLevelPattern">android.sensor.blackLevelPattern</a></li>
+            <li
+            ><a href="#static_android.sensor.maxAnalogSensitivity">android.sensor.maxAnalogSensitivity</a></li>
+            <li
+            ><a href="#static_android.sensor.orientation">android.sensor.orientation</a></li>
+            <li
+            ><a href="#static_android.sensor.profileHueSatMapDimensions">android.sensor.profileHueSatMapDimensions</a></li>
+            <li
+            ><a href="#static_android.sensor.availableTestPatternModes">android.sensor.availableTestPatternModes</a></li>
+            <li
+            ><a href="#static_android.sensor.opticalBlackRegions">android.sensor.opticalBlackRegions</a></li>
+            <li
+            ><a href="#static_android.sensor.opaqueRawSize">android.sensor.opaqueRawSize</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.sensor.exposureTime">android.sensor.exposureTime</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.frameDuration">android.sensor.frameDuration</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.sensitivity">android.sensor.sensitivity</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.timestamp">android.sensor.timestamp</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.temperature">android.sensor.temperature</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.neutralColorPoint">android.sensor.neutralColorPoint</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.noiseProfile">android.sensor.noiseProfile</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.profileHueSatMap">android.sensor.profileHueSatMap</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.profileToneCurve">android.sensor.profileToneCurve</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.greenSplit">android.sensor.greenSplit</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.testPatternData">android.sensor.testPatternData</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.testPatternMode">android.sensor.testPatternMode</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.rollingShutterSkew">android.sensor.rollingShutterSkew</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a></li>
+            <li
+            ><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_shading">shading</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.shading.mode">android.shading.mode</a></li>
+            <li
+            ><a href="#controls_android.shading.strength">android.shading.strength</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.shading.mode">android.shading.mode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.shading.availableModes">android.shading.availableModes</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_statistics">statistics</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.statistics.faceDetectMode">android.statistics.faceDetectMode</a></li>
+            <li
+            ><a href="#controls_android.statistics.histogramMode">android.statistics.histogramMode</a></li>
+            <li
+            ><a href="#controls_android.statistics.sharpnessMapMode">android.statistics.sharpnessMapMode</a></li>
+            <li
+            ><a href="#controls_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a></li>
+            <li
+            ><a href="#controls_android.statistics.lensShadingMapMode">android.statistics.lensShadingMapMode</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+
+            <li
+            ><a href="#static_android.statistics.info.availableFaceDetectModes">android.statistics.info.availableFaceDetectModes</a></li>
+            <li
+            ><a href="#static_android.statistics.info.histogramBucketCount">android.statistics.info.histogramBucketCount</a></li>
+            <li
+            ><a href="#static_android.statistics.info.maxFaceCount">android.statistics.info.maxFaceCount</a></li>
+            <li
+            ><a href="#static_android.statistics.info.maxHistogramCount">android.statistics.info.maxHistogramCount</a></li>
+            <li
+            ><a href="#static_android.statistics.info.maxSharpnessMapValue">android.statistics.info.maxSharpnessMapValue</a></li>
+            <li
+            ><a href="#static_android.statistics.info.sharpnessMapSize">android.statistics.info.sharpnessMapSize</a></li>
+            <li
+            ><a href="#static_android.statistics.info.availableHotPixelMapModes">android.statistics.info.availableHotPixelMapModes</a></li>
+            <li
+            ><a href="#static_android.statistics.info.availableLensShadingMapModes">android.statistics.info.availableLensShadingMapModes</a></li>
+
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.statistics.faceDetectMode">android.statistics.faceDetectMode</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.faceIds">android.statistics.faceIds</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.faceLandmarks">android.statistics.faceLandmarks</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.faceRectangles">android.statistics.faceRectangles</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.faceScores">android.statistics.faceScores</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.faces">android.statistics.faces</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.histogram">android.statistics.histogram</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.histogramMode">android.statistics.histogramMode</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.sharpnessMap">android.statistics.sharpnessMap</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.sharpnessMapMode">android.statistics.sharpnessMapMode</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.lensShadingCorrectionMap">android.statistics.lensShadingCorrectionMap</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.lensShadingMap">android.statistics.lensShadingMap</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.statistics.predictedColorGains">android.statistics.predictedColorGains</a></li>
+            <li
+                class="toc_deprecated"
+            ><a href="#dynamic_android.statistics.predictedColorTransform">android.statistics.predictedColorTransform</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.sceneFlicker">android.statistics.sceneFlicker</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.hotPixelMap">android.statistics.hotPixelMap</a></li>
+            <li
+            ><a href="#dynamic_android.statistics.lensShadingMapMode">android.statistics.lensShadingMapMode</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_tonemap">tonemap</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.tonemap.curveBlue">android.tonemap.curveBlue</a></li>
+            <li
+            ><a href="#controls_android.tonemap.curveGreen">android.tonemap.curveGreen</a></li>
+            <li
+            ><a href="#controls_android.tonemap.curveRed">android.tonemap.curveRed</a></li>
+            <li
+            ><a href="#controls_android.tonemap.curve">android.tonemap.curve</a></li>
+            <li
+            ><a href="#controls_android.tonemap.mode">android.tonemap.mode</a></li>
+            <li
+            ><a href="#controls_android.tonemap.gamma">android.tonemap.gamma</a></li>
+            <li
+            ><a href="#controls_android.tonemap.presetCurve">android.tonemap.presetCurve</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.tonemap.maxCurvePoints">android.tonemap.maxCurvePoints</a></li>
+            <li
+            ><a href="#static_android.tonemap.availableToneMapModes">android.tonemap.availableToneMapModes</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.tonemap.curveBlue">android.tonemap.curveBlue</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.curveGreen">android.tonemap.curveGreen</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.curveRed">android.tonemap.curveRed</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.curve">android.tonemap.curve</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.mode">android.tonemap.mode</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.gamma">android.tonemap.gamma</a></li>
+            <li
+            ><a href="#dynamic_android.tonemap.presetCurve">android.tonemap.presetCurve</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_led">led</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.led.transmit">android.led.transmit</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.led.transmit">android.led.transmit</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.led.availableLeds">android.led.availableLeds</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_info">info</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.info.supportedHardwareLevel">android.info.supportedHardwareLevel</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_blackLevel">blackLevel</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.blackLevel.lock">android.blackLevel.lock</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.blackLevel.lock">android.blackLevel.lock</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_sync">sync</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.sync.frameNumber">android.sync.frameNumber</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.sync.maxLatency">android.sync.maxLatency</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_reprocess">reprocess</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">controls</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#controls_android.reprocess.effectiveExposureFactor">android.reprocess.effectiveExposureFactor</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">dynamic</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#dynamic_android.reprocess.effectiveExposureFactor">android.reprocess.effectiveExposureFactor</a></li>
+          </ul>
+        </li>
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.reprocess.maxCaptureStall">android.reprocess.maxCaptureStall</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+    <li>
+      <span class="toc_section_header"><a href="#section_depth">depth</a></span>
+      <ul class="toc_section">
+        <li>
+          <span class="toc_kind_header">static</span>
+          <ul class="toc_section">
+            <li
+            ><a href="#static_android.depth.maxDepthSamples">android.depth.maxDepthSamples</a></li>
+            <li
+            ><a href="#static_android.depth.availableDepthStreamConfigurations">android.depth.availableDepthStreamConfigurations</a></li>
+            <li
+            ><a href="#static_android.depth.availableDepthMinFrameDurations">android.depth.availableDepthMinFrameDurations</a></li>
+            <li
+            ><a href="#static_android.depth.availableDepthStallDurations">android.depth.availableDepthStallDurations</a></li>
+            <li
+            ><a href="#static_android.depth.depthIsExclusive">android.depth.depthIsExclusive</a></li>
+          </ul>
+        </li>
+      </ul> <!-- toc_section -->
+    </li>
+  </ul>
+
+
+  <h1>Properties</h1>
+  <table class="properties">
+
+    <thead class="thead_dummy">
+      <tr>
+        <th class="th_name">Property Name</th>
+        <th class="th_type">Type</th>
+        <th class="th_description">Description</th>
+        <th class="th_units">Units</th>
+        <th class="th_range">Range</th>
+        <th class="th_tags">Tags</th>
+      </tr>
+    </thead> <!-- so that the first occurrence of thead is not
+                         above the first occurrence of tr -->
+<!-- <namespace name="android"> -->
+  <tr><td colspan="6" id="section_colorCorrection" class="section">colorCorrection</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.colorCorrection.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>color<wbr/>Correction.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">TRANSFORM_MATRIX</span>
+                    <span class="entry_type_enum_notes"><p>Use the <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> matrix
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> to do color conversion.<wbr/></p>
+<p>All advanced white balance adjustments (not specified
+by our white balance pipeline) must be disabled.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+TRANSFORM_<wbr/>MATRIX is ignored.<wbr/> The camera device will override
+this value to either FAST or HIGH_<wbr/>QUALITY.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Color correction processing must not slow down
+capture rate relative to sensor raw output.<wbr/></p>
+<p>Advanced white balance adjustments above and beyond
+the specified white balance pipeline may be applied.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+the camera device uses the last frame's AWB values
+(or defaults if AWB has never been run).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Color correction processing operates at improved
+quality but the capture rate might be reduced (relative to sensor
+raw output rate)</p>
+<p>Advanced white balance adjustments above and beyond
+the specified white balance pipeline may be applied.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+the camera device uses the last frame's AWB values
+(or defaults if AWB has never been run).<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The mode control selects how the image data is converted from the
+sensor's native color into linear sRGB color.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When auto-white balance (AWB) is enabled with <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> this
+control is overridden by the AWB routine.<wbr/> When AWB is disabled,<wbr/> the
+application controls how the color mapping is performed.<wbr/></p>
+<p>We define the expected processing pipeline below.<wbr/> For consistency
+across devices,<wbr/> this is always the case with TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>When either FULL or HIGH_<wbr/>QUALITY is used,<wbr/> the camera device may
+do additional processing but <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> will still be provided by the
+camera device (in the results) and be roughly correct.<wbr/></p>
+<p>Switching to TRANSFORM_<wbr/>MATRIX and using the data provided from
+FAST or HIGH_<wbr/>QUALITY will yield a picture with the same white point
+as what was produced by the camera device in the earlier frame.<wbr/></p>
+<p>The expected processing pipeline is as follows:</p>
+<p><img alt="White balance processing pipeline" src="images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png"/></p>
+<p>The white balance is encoded by two values,<wbr/> a 4-channel white-balance
+gain vector (applied in the Bayer domain),<wbr/> and a 3x3 color transform
+matrix (applied after demosaic).<wbr/></p>
+<p>The 4-channel white-balance gains are defined as:</p>
+<pre><code><a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> = [ R G_<wbr/>even G_<wbr/>odd B ]
+</code></pre>
+<p>where <code>G_<wbr/>even</code> is the gain for green pixels on even rows of the
+output,<wbr/> and <code>G_<wbr/>odd</code> is the gain for green pixels on the odd rows.<wbr/>
+These may be identical for a given camera device implementation; if
+the camera device does not support a separate gain for even/<wbr/>odd green
+channels,<wbr/> it will use the <code>G_<wbr/>even</code> value,<wbr/> and write <code>G_<wbr/>odd</code> equal to
+<code>G_<wbr/>even</code> in the output result metadata.<wbr/></p>
+<p>The matrices for color transforms are defined as a 9-entry vector:</p>
+<pre><code><a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> = [ I0 I1 I2 I3 I4 I5 I6 I7 I8 ]
+</code></pre>
+<p>which define a transform from input sensor colors,<wbr/> <code>P_<wbr/>in = [ r g b ]</code>,<wbr/>
+to output linear sRGB,<wbr/> <code>P_<wbr/>out = [ r' g' b' ]</code>,<wbr/></p>
+<p>with colors as follows:</p>
+<pre><code>r' = I0r + I1g + I2b
+g' = I3r + I4g + I5b
+b' = I6r + I7g + I8b
+</code></pre>
+<p>Both the input and output value ranges must match.<wbr/> Overflow/<wbr/>underflow
+values are clipped to fit within the range.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if color correction control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY should generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.colorCorrection.transform">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>color<wbr/>Correction.<wbr/>transform
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">3x3 rational matrix in row-major order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A color transform matrix to use to transform
+from sensor RGB color space to output linear sRGB color space.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Unitless scale factors
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is either set by the camera device when the request
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is not TRANSFORM_<wbr/>MATRIX,<wbr/> or
+directly by the application in the request when the
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>In the latter case,<wbr/> the camera device may round the matrix to account
+for precision issues; the final rounded matrix should be reported back
+in this matrix result metadata.<wbr/> The transform should keep the magnitude
+of the output color values within <code>[0,<wbr/> 1.<wbr/>0]</code> (assuming input color
+values is within the normalized range <code>[0,<wbr/> 1.<wbr/>0]</code>),<wbr/> or clipping may occur.<wbr/></p>
+<p>The valid range of each matrix element varies on different devices,<wbr/> but
+values within [-1.<wbr/>5,<wbr/> 3.<wbr/>0] are guaranteed not to be clipped.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.colorCorrection.gains">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>color<wbr/>Correction.<wbr/>gains
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rggbChannelVector]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">A 1D array of floats for 4 color channel gains</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Gains applying to Bayer raw color channels for
+white-balance.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Unitless gain factors
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>These per-channel gains are either set by the camera device
+when the request <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is not
+TRANSFORM_<wbr/>MATRIX,<wbr/> or directly by the application in the
+request when the <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is
+TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>The gains in the result metadata are the gains actually
+applied by the camera device to the current frame.<wbr/></p>
+<p>The valid range of gains varies on different devices,<wbr/> but gains
+between [1.<wbr/>0,<wbr/> 3.<wbr/>0] are guaranteed not to be clipped.<wbr/> Even if a given
+device allows gains below 1.<wbr/>0,<wbr/> this is usually not recommended because
+this can create color artifacts.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The 4-channel white-balance gains are defined in
+the order of <code>[R G_<wbr/>even G_<wbr/>odd B]</code>,<wbr/> where <code>G_<wbr/>even</code> is the gain
+for green pixels on even rows of the output,<wbr/> and <code>G_<wbr/>odd</code>
+is the gain for green pixels on the odd rows.<wbr/></p>
+<p>If a HAL does not support a separate gain for even/<wbr/>odd green
+channels,<wbr/> it must use the <code>G_<wbr/>even</code> value,<wbr/> and write
+<code>G_<wbr/>odd</code> equal to <code>G_<wbr/>even</code> in the output result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.colorCorrection.aberrationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No aberration correction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Aberration correction will not slow down capture rate
+relative to sensor raw output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Aberration correction operates at improved quality but the capture rate might be
+reduced (relative to sensor raw output rate)</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Mode of operation for the chromatic aberration correction algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.colorCorrection.availableAberrationModes">android.<wbr/>color<wbr/>Correction.<wbr/>available<wbr/>Aberration<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Chromatic (color) aberration is caused by the fact that different wavelengths of light
+can not focus on the same point after exiting from the lens.<wbr/> This metadata defines
+the high level control of chromatic aberration correction algorithm,<wbr/> which aims to
+minimize the chromatic artifacts that may occur along the object boundaries in an
+image.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean that camera device determined aberration
+correction will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the camera device will
+use the highest-quality aberration correction algorithms,<wbr/> even if it slows down
+capture rate.<wbr/> FAST means the camera device will not slow down capture rate when
+applying aberration correction.<wbr/></p>
+<p>LEGACY devices will always be in FAST mode.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.colorCorrection.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>color<wbr/>Correction.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">TRANSFORM_MATRIX</span>
+                    <span class="entry_type_enum_notes"><p>Use the <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> matrix
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> to do color conversion.<wbr/></p>
+<p>All advanced white balance adjustments (not specified
+by our white balance pipeline) must be disabled.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+TRANSFORM_<wbr/>MATRIX is ignored.<wbr/> The camera device will override
+this value to either FAST or HIGH_<wbr/>QUALITY.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Color correction processing must not slow down
+capture rate relative to sensor raw output.<wbr/></p>
+<p>Advanced white balance adjustments above and beyond
+the specified white balance pipeline may be applied.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+the camera device uses the last frame's AWB values
+(or defaults if AWB has never been run).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Color correction processing operates at improved
+quality but the capture rate might be reduced (relative to sensor
+raw output rate)</p>
+<p>Advanced white balance adjustments above and beyond
+the specified white balance pipeline may be applied.<wbr/></p>
+<p>If AWB is enabled with <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != OFF</code>,<wbr/> then
+the camera device uses the last frame's AWB values
+(or defaults if AWB has never been run).<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The mode control selects how the image data is converted from the
+sensor's native color into linear sRGB color.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When auto-white balance (AWB) is enabled with <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> this
+control is overridden by the AWB routine.<wbr/> When AWB is disabled,<wbr/> the
+application controls how the color mapping is performed.<wbr/></p>
+<p>We define the expected processing pipeline below.<wbr/> For consistency
+across devices,<wbr/> this is always the case with TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>When either FULL or HIGH_<wbr/>QUALITY is used,<wbr/> the camera device may
+do additional processing but <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> will still be provided by the
+camera device (in the results) and be roughly correct.<wbr/></p>
+<p>Switching to TRANSFORM_<wbr/>MATRIX and using the data provided from
+FAST or HIGH_<wbr/>QUALITY will yield a picture with the same white point
+as what was produced by the camera device in the earlier frame.<wbr/></p>
+<p>The expected processing pipeline is as follows:</p>
+<p><img alt="White balance processing pipeline" src="images/camera2/metadata/android.colorCorrection.mode/processing_pipeline.png"/></p>
+<p>The white balance is encoded by two values,<wbr/> a 4-channel white-balance
+gain vector (applied in the Bayer domain),<wbr/> and a 3x3 color transform
+matrix (applied after demosaic).<wbr/></p>
+<p>The 4-channel white-balance gains are defined as:</p>
+<pre><code><a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> = [ R G_<wbr/>even G_<wbr/>odd B ]
+</code></pre>
+<p>where <code>G_<wbr/>even</code> is the gain for green pixels on even rows of the
+output,<wbr/> and <code>G_<wbr/>odd</code> is the gain for green pixels on the odd rows.<wbr/>
+These may be identical for a given camera device implementation; if
+the camera device does not support a separate gain for even/<wbr/>odd green
+channels,<wbr/> it will use the <code>G_<wbr/>even</code> value,<wbr/> and write <code>G_<wbr/>odd</code> equal to
+<code>G_<wbr/>even</code> in the output result metadata.<wbr/></p>
+<p>The matrices for color transforms are defined as a 9-entry vector:</p>
+<pre><code><a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> = [ I0 I1 I2 I3 I4 I5 I6 I7 I8 ]
+</code></pre>
+<p>which define a transform from input sensor colors,<wbr/> <code>P_<wbr/>in = [ r g b ]</code>,<wbr/>
+to output linear sRGB,<wbr/> <code>P_<wbr/>out = [ r' g' b' ]</code>,<wbr/></p>
+<p>with colors as follows:</p>
+<pre><code>r' = I0r + I1g + I2b
+g' = I3r + I4g + I5b
+b' = I6r + I7g + I8b
+</code></pre>
+<p>Both the input and output value ranges must match.<wbr/> Overflow/<wbr/>underflow
+values are clipped to fit within the range.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if color correction control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY should generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.colorCorrection.transform">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>color<wbr/>Correction.<wbr/>transform
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">3x3 rational matrix in row-major order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A color transform matrix to use to transform
+from sensor RGB color space to output linear sRGB color space.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Unitless scale factors
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is either set by the camera device when the request
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is not TRANSFORM_<wbr/>MATRIX,<wbr/> or
+directly by the application in the request when the
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>In the latter case,<wbr/> the camera device may round the matrix to account
+for precision issues; the final rounded matrix should be reported back
+in this matrix result metadata.<wbr/> The transform should keep the magnitude
+of the output color values within <code>[0,<wbr/> 1.<wbr/>0]</code> (assuming input color
+values is within the normalized range <code>[0,<wbr/> 1.<wbr/>0]</code>),<wbr/> or clipping may occur.<wbr/></p>
+<p>The valid range of each matrix element varies on different devices,<wbr/> but
+values within [-1.<wbr/>5,<wbr/> 3.<wbr/>0] are guaranteed not to be clipped.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.colorCorrection.gains">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>color<wbr/>Correction.<wbr/>gains
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rggbChannelVector]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">A 1D array of floats for 4 color channel gains</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Gains applying to Bayer raw color channels for
+white-balance.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Unitless gain factors
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>These per-channel gains are either set by the camera device
+when the request <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is not
+TRANSFORM_<wbr/>MATRIX,<wbr/> or directly by the application in the
+request when the <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> is
+TRANSFORM_<wbr/>MATRIX.<wbr/></p>
+<p>The gains in the result metadata are the gains actually
+applied by the camera device to the current frame.<wbr/></p>
+<p>The valid range of gains varies on different devices,<wbr/> but gains
+between [1.<wbr/>0,<wbr/> 3.<wbr/>0] are guaranteed not to be clipped.<wbr/> Even if a given
+device allows gains below 1.<wbr/>0,<wbr/> this is usually not recommended because
+this can create color artifacts.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The 4-channel white-balance gains are defined in
+the order of <code>[R G_<wbr/>even G_<wbr/>odd B]</code>,<wbr/> where <code>G_<wbr/>even</code> is the gain
+for green pixels on even rows of the output,<wbr/> and <code>G_<wbr/>odd</code>
+is the gain for green pixels on the odd rows.<wbr/></p>
+<p>If a HAL does not support a separate gain for even/<wbr/>odd green
+channels,<wbr/> it must use the <code>G_<wbr/>even</code> value,<wbr/> and write
+<code>G_<wbr/>odd</code> equal to <code>G_<wbr/>even</code> in the output result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.colorCorrection.aberrationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No aberration correction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Aberration correction will not slow down capture rate
+relative to sensor raw output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Aberration correction operates at improved quality but the capture rate might be
+reduced (relative to sensor raw output rate)</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Mode of operation for the chromatic aberration correction algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.colorCorrection.availableAberrationModes">android.<wbr/>color<wbr/>Correction.<wbr/>available<wbr/>Aberration<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Chromatic (color) aberration is caused by the fact that different wavelengths of light
+can not focus on the same point after exiting from the lens.<wbr/> This metadata defines
+the high level control of chromatic aberration correction algorithm,<wbr/> which aims to
+minimize the chromatic artifacts that may occur along the object boundaries in an
+image.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean that camera device determined aberration
+correction will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the camera device will
+use the highest-quality aberration correction algorithms,<wbr/> even if it slows down
+capture rate.<wbr/> FAST means the camera device will not slow down capture rate when
+applying aberration correction.<wbr/></p>
+<p>LEGACY devices will always be in FAST mode.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.colorCorrection.availableAberrationModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>color<wbr/>Correction.<wbr/>available<wbr/>Aberration<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of aberration correction modes for <a href="#controls_android.colorCorrection.aberrationMode">android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.colorCorrection.aberrationMode">android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key lists the valid modes for <a href="#controls_android.colorCorrection.aberrationMode">android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode</a>.<wbr/>  If no
+aberration correction modes are available for a device,<wbr/> this list will solely include
+OFF mode.<wbr/> All camera devices will support either OFF or FAST mode.<wbr/></p>
+<p>Camera devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability will always list
+OFF mode.<wbr/> This includes all FULL level devices.<wbr/></p>
+<p>LEGACY devices will always only support FAST mode.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if chromatic aberration control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_control" class="section">control</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.control.aeAntibandingMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will not adjust exposure duration to
+avoid banding problems.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">50HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will adjust exposure duration to
+avoid banding problems with 50Hz illumination sources.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">60HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will adjust exposure duration to
+avoid banding problems with 60Hz illumination
+sources.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will automatically adapt its
+antibanding routine to the current illumination
+condition.<wbr/> This is the default mode if AUTO is
+available on given camera device.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired setting for the camera device's auto-exposure
+algorithm's antibanding compensation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeAvailableAntibandingModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Antibanding<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some kinds of lighting fixtures,<wbr/> such as some fluorescent
+lights,<wbr/> flicker at the rate of the power supply frequency
+(60Hz or 50Hz,<wbr/> depending on country).<wbr/> While this is
+typically not noticeable to a person,<wbr/> it can be visible to
+a camera device.<wbr/> If a camera sets its exposure time to the
+wrong value,<wbr/> the flicker may become visible in the
+viewfinder as flicker or in a final captured image,<wbr/> as a
+set of variable-brightness bands across the image.<wbr/></p>
+<p>Therefore,<wbr/> the auto-exposure routines of camera devices
+include antibanding routines that ensure that the chosen
+exposure value will not cause such banding.<wbr/> The choice of
+exposure time depends on the rate of flicker,<wbr/> which the
+camera device can detect automatically,<wbr/> or the expected
+rate can be selected by the application using this
+control.<wbr/></p>
+<p>A given camera device may not support all of the possible
+options for the antibanding mode.<wbr/> The
+<a href="#static_android.control.aeAvailableAntibandingModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Antibanding<wbr/>Modes</a> key contains
+the available modes for a given camera device.<wbr/></p>
+<p>AUTO mode is the default if it is available on given
+camera device.<wbr/> When AUTO mode is not available,<wbr/> the
+default will be either 50HZ or 60HZ,<wbr/> and both 50HZ
+and 60HZ will be available.<wbr/></p>
+<p>If manual exposure control is enabled (by setting
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> to OFF),<wbr/>
+then this setting has no effect,<wbr/> and the application must
+ensure it selects exposure times that do not cause banding
+issues.<wbr/> The <a href="#dynamic_android.statistics.sceneFlicker">android.<wbr/>statistics.<wbr/>scene<wbr/>Flicker</a> key can assist
+the application in this.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For all capture request templates,<wbr/> this field must be set
+to AUTO if AUTO mode is available.<wbr/> If AUTO is not available,<wbr/>
+the default must be either 50HZ or 60HZ,<wbr/> and both 50HZ and
+60HZ must be available.<wbr/></p>
+<p>If manual exposure control is enabled (by setting
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> to OFF),<wbr/>
+then the exposure values provided by the application must not be
+adjusted for antibanding.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aeExposureCompensation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Adjustment to auto-exposure (AE) target image
+brightness.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Compensation steps
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeCompensationRange">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The adjustment is measured as a count of steps,<wbr/> with the
+step size defined by <a href="#static_android.control.aeCompensationStep">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step</a> and the
+allowed range by <a href="#static_android.control.aeCompensationRange">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Range</a>.<wbr/></p>
+<p>For example,<wbr/> if the exposure value (EV) step is 0.<wbr/>333,<wbr/> '6'
+will mean an exposure compensation of +2 EV; -3 will mean an
+exposure compensation of -1 EV.<wbr/> One EV represents a doubling
+of image brightness.<wbr/> Note that this control will only be
+effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>!=</code> OFF.<wbr/> This control
+will take effect even when <a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> <code>== true</code>.<wbr/></p>
+<p>In the event of exposure compensation value being changed,<wbr/> camera device
+may take several frames to reach the newly requested exposure target.<wbr/>
+During that time,<wbr/> <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> field will be in the SEARCHING
+state.<wbr/> Once the new exposure target is reached,<wbr/> <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> will
+change from SEARCHING to either CONVERGED,<wbr/> LOCKED (if AE lock is enabled),<wbr/> or
+FLASH_<wbr/>REQUIRED (if the scene is too dark for still capture).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aeLock">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Auto-exposure lock is disabled; the AE algorithm
+is free to update its parameters.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Auto-exposure lock is enabled; the AE algorithm
+must not update the exposure and sensitivity parameters
+while the lock is active.<wbr/></p>
+<p><a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a> setting changes
+will still take effect while auto-exposure is locked.<wbr/></p>
+<p>Some rare LEGACY devices may not support
+this,<wbr/> in which case the value will always be overridden to OFF.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-exposure (AE) is currently locked to its latest
+calculated values.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to <code>true</code> (ON),<wbr/> the AE algorithm is locked to its latest parameters,<wbr/>
+and will not change exposure settings until the lock is set to <code>false</code> (OFF).<wbr/></p>
+<p>Note that even when AE is locked,<wbr/> the flash may be fired if
+the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is ON_<wbr/>AUTO_<wbr/>FLASH /<wbr/>
+ON_<wbr/>ALWAYS_<wbr/>FLASH /<wbr/> ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE.<wbr/></p>
+<p>When <a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a> is changed,<wbr/> even if the AE lock
+is ON,<wbr/> the camera device will still adjust its exposure value.<wbr/></p>
+<p>If AE precapture is triggered (see <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>)
+when AE is already locked,<wbr/> the camera device will not change the exposure time
+(<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>) and sensitivity (<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>)
+parameters.<wbr/> The flash may be fired if the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>
+is ON_<wbr/>AUTO_<wbr/>FLASH/<wbr/>ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE and the scene is too dark.<wbr/> If the
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is ON_<wbr/>ALWAYS_<wbr/>FLASH,<wbr/> the scene may become overexposed.<wbr/>
+Similarly,<wbr/> AE precapture trigger CANCEL has no effect when AE is already locked.<wbr/></p>
+<p>When an AE precapture sequence is triggered,<wbr/> AE unlock will not be able to unlock
+the AE if AE is locked by the camera device internally during precapture metering
+sequence In other words,<wbr/> submitting requests with AE unlock has no effect for an
+ongoing precapture metering sequence.<wbr/> Otherwise,<wbr/> the precapture metering sequence
+will never succeed in a sequence of preview requests where AE lock is always set
+to <code>false</code>.<wbr/></p>
+<p>Since the camera device has a pipeline of in-flight requests,<wbr/> the settings that
+get locked do not necessarily correspond to the settings that were present in the
+latest capture result received from the camera device,<wbr/> since additional captures
+and AE updates may have occurred even before the result was sent out.<wbr/> If an
+application is switching between automatic and manual control and wishes to eliminate
+any flicker during the switch,<wbr/> the following procedure is recommended:</p>
+<ol>
+<li>Starting in auto-AE mode:</li>
+<li>Lock AE</li>
+<li>Wait for the first result to be output that has the AE locked</li>
+<li>Copy exposure settings from that result into a request,<wbr/> set the request to manual AE</li>
+<li>Submit the capture request,<wbr/> proceed to run manual AE as desired.<wbr/></li>
+</ol>
+<p>See <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> for AE lock related state transition details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aeMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's autoexposure routine is disabled.<wbr/></p>
+<p>The application-selected <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> are used by the camera
+device,<wbr/> along with android.<wbr/>flash.<wbr/>* fields,<wbr/> if there's
+a flash unit for this camera device.<wbr/></p>
+<p>Note that auto-white balance (AWB) and auto-focus (AF)
+behavior is device dependent when AE is in OFF mode.<wbr/>
+To have consistent behavior across different devices,<wbr/>
+it is recommended to either set AWB and AF to OFF mode
+or lock AWB and AF before setting AE to OFF.<wbr/>
+See <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a>,<wbr/> and <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>
+for more details.<wbr/></p>
+<p>LEGACY devices do not support the OFF mode and will
+override attempts to use this value to ON.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's autoexposure routine is active,<wbr/>
+with no flash control.<wbr/></p>
+<p>The application's values for
+<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> are ignored.<wbr/> The
+application has control over the various
+android.<wbr/>flash.<wbr/>* fields.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_AUTO_FLASH</span>
+                    <span class="entry_type_enum_notes"><p>Like ON,<wbr/> except that the camera device also controls
+the camera's flash unit,<wbr/> firing it in low-light
+conditions.<wbr/></p>
+<p>The flash may be fired during a precapture sequence
+(triggered by <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>) and
+may be fired for captures for which the
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> field is set to
+STILL_<wbr/>CAPTURE</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_ALWAYS_FLASH</span>
+                    <span class="entry_type_enum_notes"><p>Like ON,<wbr/> except that the camera device also controls
+the camera's flash unit,<wbr/> always firing it for still
+captures.<wbr/></p>
+<p>The flash may be fired during a precapture sequence
+(triggered by <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>) and
+will always be fired for captures for which the
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> field is set to
+STILL_<wbr/>CAPTURE</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_AUTO_FLASH_REDEYE</span>
+                    <span class="entry_type_enum_notes"><p>Like ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/> but with automatic red eye
+reduction.<wbr/></p>
+<p>If deemed necessary by the camera device,<wbr/> a red eye
+reduction flash will fire during the precapture
+sequence.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired mode for the camera device's
+auto-exposure routine.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeAvailableModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is
+AUTO.<wbr/></p>
+<p>When set to any of the ON modes,<wbr/> the camera device's
+auto-exposure routine is enabled,<wbr/> overriding the
+application's selected exposure time,<wbr/> sensor sensitivity,<wbr/>
+and frame duration (<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>).<wbr/> If one of the FLASH modes
+is selected,<wbr/> the camera device's flash unit controls are
+also overridden.<wbr/></p>
+<p>The FLASH modes are only available if the camera device
+has a flash unit (<a href="#static_android.flash.info.available">android.<wbr/>flash.<wbr/>info.<wbr/>available</a> is <code>true</code>).<wbr/></p>
+<p>If flash TORCH mode is desired,<wbr/> this field must be set to
+ON or OFF,<wbr/> and <a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> set to TORCH.<wbr/></p>
+<p>When set to any of the ON modes,<wbr/> the values chosen by the
+camera device auto-exposure routine for the overridden
+fields for a given capture will be available in its
+CaptureResult.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aeRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-exposure adjustment.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAe">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Ae</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of regions supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAe">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Ae</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must be within <code>[0,<wbr/> 1000]</code>,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other exposure metering regions,<wbr/> so if only one
+region is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with 0
+weight is ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/>  If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aeTargetFpsRange">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Range over which the auto-exposure routine can
+adjust the capture frame rate to maintain good
+exposure.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Frames per second (FPS)
+            </td>
+
+            <td class="entry_range">
+              <p>Any of the entries in <a href="#static_android.control.aeAvailableTargetFpsRanges">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Target<wbr/>Fps<wbr/>Ranges</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only constrains auto-exposure (AE) algorithm,<wbr/> not
+manual control of <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.aePrecaptureTrigger">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">IDLE</span>
+                    <span class="entry_type_enum_notes"><p>The trigger is idle.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">START</span>
+                    <span class="entry_type_enum_notes"><p>The precapture metering sequence will be started
+by the camera device.<wbr/></p>
+<p>The exact effect of the precapture trigger depends on
+the current AE mode and state.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANCEL</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will cancel any currently active or completed
+precapture metering sequence,<wbr/> the auto-exposure routine will return to its
+initial state.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will trigger a precapture
+metering sequence when it processes this request.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is normally set to IDLE,<wbr/> or is not
+included at all in the request settings.<wbr/> When included and
+set to START,<wbr/> the camera device will trigger the auto-exposure (AE)
+precapture metering sequence.<wbr/></p>
+<p>When set to CANCEL,<wbr/> the camera device will cancel any active
+precapture metering trigger,<wbr/> and return to its initial AE state.<wbr/>
+If a precapture metering sequence is already completed,<wbr/> and the camera
+device has implicitly locked the AE for subsequent still capture,<wbr/> the
+CANCEL trigger will unlock the AE and return to its initial AE state.<wbr/></p>
+<p>The precapture sequence should be triggered before starting a
+high-quality still capture for final metering decisions to
+be made,<wbr/> and for firing pre-capture flash pulses to estimate
+scene brightness and required final capture flash power,<wbr/> when
+the flash is enabled.<wbr/></p>
+<p>Normally,<wbr/> this entry should be set to START for only a
+single request,<wbr/> and the application should wait until the
+sequence completes before starting a new one.<wbr/></p>
+<p>When a precapture metering sequence is finished,<wbr/> the camera device
+may lock the auto-exposure routine internally to be able to accurately expose the
+subsequent still capture image (<code><a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE</code>).<wbr/>
+For this case,<wbr/> the AE may not resume normal scan if no subsequent still capture is
+submitted.<wbr/> To ensure that the AE routine restarts normal scan,<wbr/> the application should
+submit a request with <code><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> == true</code>,<wbr/> followed by a request
+with <code><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> == false</code>,<wbr/> if the application decides not to submit a
+still capture request after the precapture sequence completes.<wbr/> Alternatively,<wbr/> for
+API level 23 or newer devices,<wbr/> the CANCEL can be used to unlock the camera device
+internally locked AE if the application doesn't submit a still capture request after
+the AE precapture trigger.<wbr/> Note that,<wbr/> the CANCEL was added in API level 23,<wbr/> and must not
+be used in devices that have earlier API levels.<wbr/></p>
+<p>The exact effect of auto-exposure (AE) precapture trigger
+depends on the current AE mode and state; see
+<a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> for AE precapture state transition
+details.<wbr/></p>
+<p>On LEGACY-level devices,<wbr/> the precapture trigger is not supported;
+capturing a high-resolution JPEG image will automatically trigger a
+precapture sequence before the high-resolution capture,<wbr/> including
+potentially firing a pre-capture flash.<wbr/></p>
+<p>Using the precapture trigger and the auto-focus trigger <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>
+simultaneously is allowed.<wbr/> However,<wbr/> since these triggers often require cooperation between
+the auto-focus and auto-exposure routines (for example,<wbr/> the may need to be enabled for a
+focus sweep),<wbr/> the camera device may delay acting on a later trigger until the previous
+trigger has been fully handled.<wbr/> This may lead to longer intervals between the trigger and
+changes to <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> indicating the start of the precapture sequence,<wbr/> for
+example.<wbr/></p>
+<p>If both the precapture and the auto-focus trigger are activated on the same request,<wbr/> then
+the camera device will complete them in the optimal order for that device.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must support triggering the AE precapture trigger while an AF trigger is active
+(and vice versa),<wbr/> or at the same time as the AF trigger.<wbr/>  It is acceptable for the HAL to
+treat these as two consecutive triggers,<wbr/> for example handling the AF trigger and then the
+AE trigger.<wbr/>  Or the HAL may choose to optimize the case with both triggers fired at once,<wbr/>
+to minimize the latency for converging both focus and exposure/<wbr/>flash usage.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.afMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The auto-focus routine does not control the lens;
+<a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> is controlled by the
+application.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>Basic automatic focus mode.<wbr/></p>
+<p>In this mode,<wbr/> the lens does not move unless
+the autofocus trigger action is called.<wbr/> When that trigger
+is activated,<wbr/> AF will transition to ACTIVE_<wbr/>SCAN,<wbr/> then to
+the outcome of the scan (FOCUSED or NOT_<wbr/>FOCUSED).<wbr/></p>
+<p>Always supported if lens is not fixed focus.<wbr/></p>
+<p>Use <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> to determine if lens
+is fixed-focus.<wbr/></p>
+<p>Triggering AF_<wbr/>CANCEL resets the lens position to default,<wbr/>
+and sets the AF state to INACTIVE.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MACRO</span>
+                    <span class="entry_type_enum_notes"><p>Close-up focusing mode.<wbr/></p>
+<p>In this mode,<wbr/> the lens does not move unless the
+autofocus trigger action is called.<wbr/> When that trigger is
+activated,<wbr/> AF will transition to ACTIVE_<wbr/>SCAN,<wbr/> then to
+the outcome of the scan (FOCUSED or NOT_<wbr/>FOCUSED).<wbr/> This
+mode is optimized for focusing on objects very close to
+the camera.<wbr/></p>
+<p>When that trigger is activated,<wbr/> AF will transition to
+ACTIVE_<wbr/>SCAN,<wbr/> then to the outcome of the scan (FOCUSED or
+NOT_<wbr/>FOCUSED).<wbr/> Triggering cancel AF resets the lens
+position to default,<wbr/> and sets the AF state to
+INACTIVE.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONTINUOUS_VIDEO</span>
+                    <span class="entry_type_enum_notes"><p>In this mode,<wbr/> the AF algorithm modifies the lens
+position continually to attempt to provide a
+constantly-in-focus image stream.<wbr/></p>
+<p>The focusing behavior should be suitable for good quality
+video recording; typically this means slower focus
+movement and no overshoots.<wbr/> When the AF trigger is not
+involved,<wbr/> the AF algorithm should start in INACTIVE state,<wbr/>
+and then transition into PASSIVE_<wbr/>SCAN and PASSIVE_<wbr/>FOCUSED
+states as appropriate.<wbr/> When the AF trigger is activated,<wbr/>
+the algorithm should immediately transition into
+AF_<wbr/>FOCUSED or AF_<wbr/>NOT_<wbr/>FOCUSED as appropriate,<wbr/> and lock the
+lens position until a cancel AF trigger is received.<wbr/></p>
+<p>Once cancel is received,<wbr/> the algorithm should transition
+back to INACTIVE and resume passive scan.<wbr/> Note that this
+behavior is not identical to CONTINUOUS_<wbr/>PICTURE,<wbr/> since an
+ongoing PASSIVE_<wbr/>SCAN must immediately be
+canceled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONTINUOUS_PICTURE</span>
+                    <span class="entry_type_enum_notes"><p>In this mode,<wbr/> the AF algorithm modifies the lens
+position continually to attempt to provide a
+constantly-in-focus image stream.<wbr/></p>
+<p>The focusing behavior should be suitable for still image
+capture; typically this means focusing as fast as
+possible.<wbr/> When the AF trigger is not involved,<wbr/> the AF
+algorithm should start in INACTIVE state,<wbr/> and then
+transition into PASSIVE_<wbr/>SCAN and PASSIVE_<wbr/>FOCUSED states as
+appropriate as it attempts to maintain focus.<wbr/> When the AF
+trigger is activated,<wbr/> the algorithm should finish its
+PASSIVE_<wbr/>SCAN if active,<wbr/> and then transition into
+AF_<wbr/>FOCUSED or AF_<wbr/>NOT_<wbr/>FOCUSED as appropriate,<wbr/> and lock the
+lens position until a cancel AF trigger is received.<wbr/></p>
+<p>When the AF cancel trigger is activated,<wbr/> the algorithm
+should transition back to INACTIVE and then act as if it
+has just been started.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">EDOF</span>
+                    <span class="entry_type_enum_notes"><p>Extended depth of field (digital focus) mode.<wbr/></p>
+<p>The camera device will produce images with an extended
+depth of field automatically; no special focusing
+operations need to be done before taking a picture.<wbr/></p>
+<p>AF triggers are ignored,<wbr/> and the AF state will always be
+INACTIVE.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-focus (AF) is currently enabled,<wbr/> and what
+mode it is set to.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.afAvailableModes">android.<wbr/>control.<wbr/>af<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> = AUTO and the lens is not fixed focus
+(i.<wbr/>e.<wbr/> <code><a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> &gt; 0</code>).<wbr/> Also note that
+when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is OFF,<wbr/> the behavior of AF is device
+dependent.<wbr/> It is recommended to lock AF by using <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a> before
+setting <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> to OFF,<wbr/> or set AF mode to OFF when AE is OFF.<wbr/></p>
+<p>If the lens is controlled by the camera device auto-focus algorithm,<wbr/>
+the camera device will report the current AF status in <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a>
+in result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When afMode is AUTO or MACRO,<wbr/> the lens must not move until an AF trigger is sent in a
+request (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a> <code>==</code> START).<wbr/> After an AF trigger,<wbr/> the afState will end
+up with either FOCUSED_<wbr/>LOCKED or NOT_<wbr/>FOCUSED_<wbr/>LOCKED state (see
+<a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for detailed state transitions),<wbr/> which indicates that the lens is
+locked and will not move.<wbr/> If camera movement (e.<wbr/>g.<wbr/> tilting camera) causes the lens to move
+after the lens is locked,<wbr/> the HAL must compensate this movement appropriately such that
+the same focal plane remains in focus.<wbr/></p>
+<p>When afMode is one of the continuous auto focus modes,<wbr/> the HAL is free to start a AF
+scan whenever it's not locked.<wbr/> When the lens is locked after an AF trigger
+(see <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for detailed state transitions),<wbr/> the HAL should maintain the
+same lock behavior as above.<wbr/></p>
+<p>When afMode is OFF,<wbr/> the application controls focus manually.<wbr/> The accuracy of the
+focus distance control depends on the <a href="#static_android.lens.info.focusDistanceCalibration">android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration</a>.<wbr/>
+However,<wbr/> the lens must not move regardless of the camera movement for any focus distance
+manual control.<wbr/></p>
+<p>To put this in concrete terms,<wbr/> if the camera has lens elements which may move based on
+camera orientation or motion (e.<wbr/>g.<wbr/> due to gravity),<wbr/> then the HAL must drive the lens to
+remain in a fixed position invariant to the camera's orientation or motion,<wbr/> for example,<wbr/>
+by using accelerometer measurements in the lens control logic.<wbr/> This is a typical issue
+that will arise on camera modules with open-loop VCMs.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.afRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-focus.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAf">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Af</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of focus areas supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAf">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Af</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must be within <code>[0,<wbr/> 1000]</code>,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other metering regions,<wbr/> so if only one region
+is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with 0 weight is
+ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/> If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.afTrigger">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Trigger
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">IDLE</span>
+                    <span class="entry_type_enum_notes"><p>The trigger is idle.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">START</span>
+                    <span class="entry_type_enum_notes"><p>Autofocus will trigger now.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANCEL</span>
+                    <span class="entry_type_enum_notes"><p>Autofocus will return to its initial
+state,<wbr/> and cancel any currently active trigger.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will trigger autofocus for this request.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is normally set to IDLE,<wbr/> or is not
+included at all in the request settings.<wbr/></p>
+<p>When included and set to START,<wbr/> the camera device will trigger the
+autofocus algorithm.<wbr/> If autofocus is disabled,<wbr/> this trigger has no effect.<wbr/></p>
+<p>When set to CANCEL,<wbr/> the camera device will cancel any active trigger,<wbr/>
+and return to its initial AF state.<wbr/></p>
+<p>Generally,<wbr/> applications should set this entry to START or CANCEL for only a
+single capture,<wbr/> and then return it to IDLE (or not set at all).<wbr/> Specifying
+START for multiple captures in a row means restarting the AF operation over
+and over again.<wbr/></p>
+<p>See <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for what the trigger means for each AF mode.<wbr/></p>
+<p>Using the autofocus trigger and the precapture trigger <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>
+simultaneously is allowed.<wbr/> However,<wbr/> since these triggers often require cooperation between
+the auto-focus and auto-exposure routines (for example,<wbr/> the may need to be enabled for a
+focus sweep),<wbr/> the camera device may delay acting on a later trigger until the previous
+trigger has been fully handled.<wbr/> This may lead to longer intervals between the trigger and
+changes to <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a>,<wbr/> for example.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must support triggering the AF trigger while an AE precapture trigger is active
+(and vice versa),<wbr/> or at the same time as the AE trigger.<wbr/>  It is acceptable for the HAL to
+treat these as two consecutive triggers,<wbr/> for example handling the AF trigger and then the
+AE trigger.<wbr/>  Or the HAL may choose to optimize the case with both triggers fired at once,<wbr/>
+to minimize the latency for converging both focus and exposure/<wbr/>flash usage.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.awbLock">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Auto-white balance lock is disabled; the AWB
+algorithm is free to update its parameters if in AUTO
+mode.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Auto-white balance lock is enabled; the AWB
+algorithm will not update its parameters while the lock
+is active.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-white balance (AWB) is currently locked to its
+latest calculated values.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to <code>true</code> (ON),<wbr/> the AWB algorithm is locked to its latest parameters,<wbr/>
+and will not change color balance settings until the lock is set to <code>false</code> (OFF).<wbr/></p>
+<p>Since the camera device has a pipeline of in-flight requests,<wbr/> the settings that
+get locked do not necessarily correspond to the settings that were present in the
+latest capture result received from the camera device,<wbr/> since additional captures
+and AWB updates may have occurred even before the result was sent out.<wbr/> If an
+application is switching between automatic and manual control and wishes to eliminate
+any flicker during the switch,<wbr/> the following procedure is recommended:</p>
+<ol>
+<li>Starting in auto-AWB mode:</li>
+<li>Lock AWB</li>
+<li>Wait for the first result to be output that has the AWB locked</li>
+<li>Copy AWB settings from that result into a request,<wbr/> set the request to manual AWB</li>
+<li>Submit the capture request,<wbr/> proceed to run manual AWB as desired.<wbr/></li>
+</ol>
+<p>Note that AWB lock is only meaningful when
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> is in the AUTO mode; in other modes,<wbr/>
+AWB is already fixed to a specific setting.<wbr/></p>
+<p>Some LEGACY devices may not support ON; the value is then overridden to OFF.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.awbMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled.<wbr/></p>
+<p>The application-selected color transform matrix
+(<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>) and gains
+(<a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a>) are used by the camera
+device for manual white balance control.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is active.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">INCANDESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses incandescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant A.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FLUORESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses fluorescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant F2.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">WARM_FLUORESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses warm fluorescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant F4.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DAYLIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses daylight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant D65.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CLOUDY_DAYLIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses cloudy daylight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TWILIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses twilight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SHADE</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses shade light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-white balance (AWB) is currently setting the color
+transform fields,<wbr/> and what its illumination target
+is.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.awbAvailableModes">android.<wbr/>control.<wbr/>awb<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is AUTO.<wbr/></p>
+<p>When set to the ON mode,<wbr/> the camera device's auto-white balance
+routine is enabled,<wbr/> overriding the application's selected
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/> <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a>.<wbr/> Note that when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>
+is OFF,<wbr/> the behavior of AWB is device dependent.<wbr/> It is recommened to
+also set AWB mode to OFF or lock AWB by using <a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> before
+setting AE mode to OFF.<wbr/></p>
+<p>When set to the OFF mode,<wbr/> the camera device's auto-white balance
+routine is disabled.<wbr/> The application manually controls the white
+balance by <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/> <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a>
+and <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a>.<wbr/></p>
+<p>When set to any other modes,<wbr/> the camera device's auto-white
+balance routine is disabled.<wbr/> The camera device uses each
+particular illumination target for white balance
+adjustment.<wbr/> The application's values for
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/>
+<a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> are ignored.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.awbRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>awb<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-white-balance illuminant
+estimation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAwb">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Awb</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of regions supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAwb">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Awb</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must range from 0 to 1000,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other white balance metering regions,<wbr/> so if
+only one region is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with
+0 weight is ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/>  If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.captureIntent">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>capture<wbr/>Intent
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CUSTOM</span>
+                    <span class="entry_type_enum_notes"><p>The goal of this request doesn't fall into the other
+categories.<wbr/> The camera device will default to preview-like
+behavior.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PREVIEW</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a preview-like use case.<wbr/></p>
+<p>The precapture trigger may be used to start off a metering
+w/<wbr/>flash sequence.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STILL_CAPTURE</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a still capture-type
+use case.<wbr/></p>
+<p>If the flash unit is under automatic control,<wbr/> it may fire as needed.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">VIDEO_RECORD</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a video recording
+use case.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">VIDEO_SNAPSHOT</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a video snapshot (still
+image while recording video) use case.<wbr/></p>
+<p>The camera device should take the highest-quality image
+possible (given the other settings) without disrupting the
+frame rate of video recording.<wbr/>  </p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a ZSL usecase; the
+application will stream full-resolution images and
+reprocess one or several later for a final
+capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MANUAL</span>
+                    <span class="entry_type_enum_notes"><p>This request is for manual capture use case where
+the applications want to directly control the capture parameters.<wbr/></p>
+<p>For example,<wbr/> the application may wish to manually control
+<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> etc.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Information to the camera device 3A (auto-exposure,<wbr/>
+auto-focus,<wbr/> auto-white balance) routines about the purpose
+of this capture,<wbr/> to help the camera device to decide optimal 3A
+strategy.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control (except for MANUAL) is only effective if
+<code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> != OFF</code> and any 3A routine is active.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG will be supported if <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>
+contains PRIVATE_<wbr/>REPROCESSING or YUV_<wbr/>REPROCESSING.<wbr/> MANUAL will be supported if
+<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains MANUAL_<wbr/>SENSOR.<wbr/> Other intent values are
+always supported.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.effectMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>effect<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No color effect will be applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MONO</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "monocolor" effect where the image is mapped into
+a single color.<wbr/></p>
+<p>This will typically be grayscale.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NEGATIVE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "photo-negative" effect where the image's colors
+are inverted.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SOLARIZE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "solarisation" effect (Sabattier effect) where the
+image is wholly or partially reversed in
+tone.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SEPIA</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "sepia" effect where the image is mapped into warm
+gray,<wbr/> red,<wbr/> and brown tones.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">POSTERIZE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "posterization" effect where the image uses
+discrete regions of tone rather than a continuous
+gradient of tones.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">WHITEBOARD</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "whiteboard" effect where the image is typically displayed
+as regions of white,<wbr/> with black or grey details.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BLACKBOARD</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "blackboard" effect where the image is typically displayed
+as regions of black,<wbr/> with white or grey details.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AQUA</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>An "aqua" effect where a blue hue is added to the image.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A special color effect to apply.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableEffects">android.<wbr/>control.<wbr/>available<wbr/>Effects</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When this mode is set,<wbr/> a color effect will be applied
+to images produced by the camera device.<wbr/> The interpretation
+and implementation of these color effects is left to the
+implementor of the camera device,<wbr/> and should not be
+depended on to be consistent (or present) across all
+devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Full application control of pipeline.<wbr/></p>
+<p>All control by the device's metering and focusing (3A)
+routines is disabled,<wbr/> and no other settings in
+android.<wbr/>control.<wbr/>* have any effect,<wbr/> except that
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> may be used by the camera
+device to select post-processing values for processing
+blocks that do not allow for manual control,<wbr/> or are not
+exposed by the camera API.<wbr/></p>
+<p>However,<wbr/> the camera device's 3A routines may continue to
+collect statistics and update their internal state so that
+when control is switched to AUTO mode,<wbr/> good control values
+can be immediately applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>Use settings for each individual 3A routine.<wbr/></p>
+<p>Manual control of capture parameters is disabled.<wbr/> All
+controls in android.<wbr/>control.<wbr/>* besides sceneMode take
+effect.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">USE_SCENE_MODE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Use a specific scene mode.<wbr/></p>
+<p>Enabling this disables control.<wbr/>aeMode,<wbr/> control.<wbr/>awbMode and
+control.<wbr/>afMode controls; the camera device will ignore
+those settings while USE_<wbr/>SCENE_<wbr/>MODE is active (except for
+FACE_<wbr/>PRIORITY scene mode).<wbr/> Other control entries are still active.<wbr/>
+This setting can only be used if scene mode is supported (i.<wbr/>e.<wbr/>
+<a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a>
+contain some modes other than DISABLED).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">OFF_KEEP_STATE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Same as OFF mode,<wbr/> except that this capture will not be
+used by camera device background auto-exposure,<wbr/> auto-white balance and
+auto-focus algorithms (3A) to update their statistics.<wbr/></p>
+<p>Specifically,<wbr/> the 3A routines are locked to the last
+values set from a request with AUTO,<wbr/> OFF,<wbr/> or
+USE_<wbr/>SCENE_<wbr/>MODE,<wbr/> and any statistics or state updates
+collected from manual captures with OFF_<wbr/>KEEP_<wbr/>STATE will be
+discarded by the camera device.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Overall mode of 3A (auto-exposure,<wbr/> auto-white-balance,<wbr/> auto-focus) control
+routines.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableModes">android.<wbr/>control.<wbr/>available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is a top-level 3A control switch.<wbr/> When set to OFF,<wbr/> all 3A control
+by the camera device is disabled.<wbr/> The application must set the fields for
+capture parameters itself.<wbr/></p>
+<p>When set to AUTO,<wbr/> the individual algorithm controls in
+android.<wbr/>control.<wbr/>* are in effect,<wbr/> such as <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>.<wbr/></p>
+<p>When set to USE_<wbr/>SCENE_<wbr/>MODE,<wbr/> the individual controls in
+android.<wbr/>control.<wbr/>* are mostly disabled,<wbr/> and the camera device implements
+one of the scene mode settings (such as ACTION,<wbr/> SUNSET,<wbr/> or PARTY)
+as it wishes.<wbr/> The camera device scene mode 3A settings are provided by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html">capture results</a>.<wbr/></p>
+<p>When set to OFF_<wbr/>KEEP_<wbr/>STATE,<wbr/> it is similar to OFF mode,<wbr/> the only difference
+is that this frame will not be used by camera device background 3A statistics
+update,<wbr/> as if this frame is never captured.<wbr/> This mode can be used in the scenario
+where the application doesn't want a 3A manual control capture to affect
+the subsequent auto 3A capture results.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.sceneMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>scene<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">DISABLED</span>
+                    <span class="entry_type_enum_value">0</span>
+                    <span class="entry_type_enum_notes"><p>Indicates that no scene modes are set for a given capture request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FACE_PRIORITY</span>
+                    <span class="entry_type_enum_notes"><p>If face detection support exists,<wbr/> use face
+detection data for auto-focus,<wbr/> auto-white balance,<wbr/> and
+auto-exposure routines.<wbr/></p>
+<p>If face detection statistics are disabled
+(i.<wbr/>e.<wbr/> <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> is set to OFF),<wbr/>
+this should still operate correctly (but will not return
+face detection statistics to the framework).<wbr/></p>
+<p>Unlike the other scene modes,<wbr/> <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+remain active when FACE_<wbr/>PRIORITY is set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ACTION</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of quickly moving objects.<wbr/></p>
+<p>Similar to SPORTS.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PORTRAIT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for still photos of people.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">LANDSCAPE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of distant macroscopic objects.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for low-light settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NIGHT_PORTRAIT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for still photos of people in low-light
+settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">THEATRE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim,<wbr/> indoor settings where flash must
+remain off.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BEACH</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for bright,<wbr/> outdoor beach settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SNOW</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for bright,<wbr/> outdoor settings containing snow.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SUNSET</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for scenes of the setting sun.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STEADYPHOTO</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized to avoid blurry photos due to small amounts of
+device motion (for example: due to hand shake).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FIREWORKS</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for nighttime photos of fireworks.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SPORTS</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of quickly moving people.<wbr/></p>
+<p>Similar to ACTION.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PARTY</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim,<wbr/> indoor settings with multiple moving
+people.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANDLELIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim settings where the main light source
+is a flame.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BARCODE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for accurately capturing a photo of barcode
+for use by camera applications that wish to read the
+barcode value.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_SPEED_VIDEO</span>
+                    <span class="entry_type_enum_deprecated">[deprecated]</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>This is deprecated,<wbr/> please use <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>
+and <a href="https://developer.android.com/reference/android/hardware/camera2/CameraConstrainedHighSpeedCaptureSession.html#createHighSpeedRequestList">CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList</a>
+for high speed video recording.<wbr/></p>
+<p>Optimized for high speed video recording (frame rate &gt;=60fps) use case.<wbr/></p>
+<p>The supported high speed video sizes and fps ranges are specified in
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/> To get desired
+output frame rates,<wbr/> the application is only allowed to select video size
+and fps range combinations listed in this static metadata.<wbr/> The fps range
+can be control via <a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a>.<wbr/></p>
+<p>In this mode,<wbr/> the camera device will override aeMode,<wbr/> awbMode,<wbr/> and afMode to
+ON,<wbr/> ON,<wbr/> and CONTINUOUS_<wbr/>VIDEO,<wbr/> respectively.<wbr/> All post-processing block mode
+controls will be overridden to be FAST.<wbr/> Therefore,<wbr/> no manual control of capture
+and post-processing parameters is possible.<wbr/> All other controls operate the
+same as when <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == AUTO.<wbr/> This means that all other
+android.<wbr/>control.<wbr/>* fields continue to work,<wbr/> such as</p>
+<ul>
+<li><a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a></li>
+<li><a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a></li>
+<li><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.effectMode">android.<wbr/>control.<wbr/>effect<wbr/>Mode</a></li>
+<li><a href="#controls_android.control.aeRegions">android.<wbr/>control.<wbr/>ae<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afRegions">android.<wbr/>control.<wbr/>af<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.awbRegions">android.<wbr/>control.<wbr/>awb<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a></li>
+<li><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a></li>
+</ul>
+<p>Outside of android.<wbr/>control.<wbr/>*,<wbr/> the following controls will work:</p>
+<ul>
+<li><a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> (automatic flash for still capture will not work since aeMode is ON)</li>
+<li><a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a> (if it is supported)</li>
+<li><a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a></li>
+<li><a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a></li>
+</ul>
+<p>For high speed recording use case,<wbr/> the actual maximum supported frame rate may
+be lower than what camera can output,<wbr/> depending on the destination Surfaces for
+the image data.<wbr/> For example,<wbr/> if the destination surface is from video encoder,<wbr/>
+the application need check if the video encoder is capable of supporting the
+high frame rate for a given video size,<wbr/> or it will end up with lower recording
+frame rate.<wbr/> If the destination surface is from preview window,<wbr/> the preview frame
+rate will be bounded by the screen refresh rate.<wbr/></p>
+<p>The camera device will only support up to 2 output high speed streams
+(processed non-stalling format defined in <a href="#static_android.request.maxNumOutputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Streams</a>)
+in this mode.<wbr/> This control will be effective only if all of below conditions are true:</p>
+<ul>
+<li>The application created no more than maxNumHighSpeedStreams processed non-stalling
+format output streams,<wbr/> where maxNumHighSpeedStreams is calculated as
+min(2,<wbr/> <a href="#static_android.request.maxNumOutputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Streams</a>[Processed (but not-stalling)]).<wbr/></li>
+<li>The stream sizes are selected from the sizes reported by
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/></li>
+<li>No processed non-stalling or raw streams are configured.<wbr/></li>
+</ul>
+<p>When above conditions are NOT satistied,<wbr/> the controls of this mode and
+<a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a> will be ignored by the camera device,<wbr/>
+the camera device will fall back to <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> <code>==</code> AUTO,<wbr/>
+and the returned capture result metadata will give the fps range choosen
+by the camera device.<wbr/></p>
+<p>Switching into or out of this mode may trigger some camera ISP/<wbr/>sensor
+reconfigurations,<wbr/> which may introduce extra latency.<wbr/> It is recommended that
+the application avoids unnecessary scene mode switch as much as possible.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HDR</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Turn on a device-specific high dynamic range (HDR) mode.<wbr/></p>
+<p>In this scene mode,<wbr/> the camera device captures images
+that keep a larger range of scene illumination levels
+visible in the final image.<wbr/> For example,<wbr/> when taking a
+picture of a object in front of a bright window,<wbr/> both
+the object and the scene through the window may be
+visible when using HDR mode,<wbr/> while in normal AUTO mode,<wbr/>
+one or the other may be poorly exposed.<wbr/> As a tradeoff,<wbr/>
+HDR mode generally takes much longer to capture a single
+image,<wbr/> has no user control,<wbr/> and may have other artifacts
+depending on the HDR method used.<wbr/></p>
+<p>Therefore,<wbr/> HDR captures operate at a much slower rate
+than regular captures.<wbr/></p>
+<p>In this mode,<wbr/> on LIMITED or FULL devices,<wbr/> when a request
+is made with a <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> of
+STILL_<wbr/>CAPTURE,<wbr/> the camera device will capture an image
+using a high dynamic range capture technique.<wbr/>  On LEGACY
+devices,<wbr/> captures that target a JPEG-format output will
+be captured with HDR,<wbr/> and the capture intent is not
+relevant.<wbr/></p>
+<p>The HDR capture may involve the device capturing a burst
+of images internally and combining them into one,<wbr/> or it
+may involve the device using specialized high dynamic
+range capture hardware.<wbr/> In all cases,<wbr/> a single image is
+produced in response to a capture request submitted
+while in HDR mode.<wbr/></p>
+<p>Since substantial post-processing is generally needed to
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/>  For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_notes"><p>Same as FACE_<wbr/>PRIORITY scene mode,<wbr/> except that the camera
+device will choose higher sensitivity values (<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>)
+under low light conditions.<wbr/></p>
+<p>The camera device may be tuned to expose the images in a reduced
+sensitivity range to produce the best quality images.<wbr/> For example,<wbr/>
+if the <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a> gives range of [100,<wbr/> 1600],<wbr/>
+the camera device auto-exposure routine tuning process may limit the actual
+exposure sensitivity range to [100,<wbr/> 1200] to ensure that the noise level isn't
+exessive in order to preserve the image quality.<wbr/> Under this situation,<wbr/> the image under
+low light may be under-exposed when the sensor max exposure time (bounded by the
+<a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a> when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is one of the
+ON_<wbr/>* modes) and effective max sensitivity are reached.<wbr/> This scene mode allows the
+camera device auto-exposure routine to increase the sensitivity up to the max
+sensitivity specified by <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a> when the scene is too
+dark and the max exposure time is reached.<wbr/> The captured images may be noisier
+compared with the images captured in normal FACE_<wbr/>PRIORITY mode; therefore,<wbr/> it is
+recommended that the application only use this scene mode when it is capable of
+reducing the noise level of the captured images.<wbr/></p>
+<p>Unlike the other scene modes,<wbr/> <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">100</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">127</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Control for which scene mode is currently active.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Scene modes are custom camera modes optimized for a certain set of conditions and
+capture settings.<wbr/></p>
+<p>This is the mode that that is active when
+<code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == USE_<wbr/>SCENE_<wbr/>MODE</code>.<wbr/> Aside from FACE_<wbr/>PRIORITY,<wbr/> these modes will
+disable <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+while in use.<wbr/></p>
+<p>The interpretation and implementation of these scene modes is left
+to the implementor of the camera device.<wbr/> Their behavior will not be
+consistent across all devices,<wbr/> and any given device may only implement
+a subset of these modes.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL implementations that include scene modes are expected to provide
+the per-scene settings to use for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> in
+<a href="#static_android.control.sceneModeOverrides">android.<wbr/>control.<wbr/>scene<wbr/>Mode<wbr/>Overrides</a>.<wbr/></p>
+<p>For HIGH_<wbr/>SPEED_<wbr/>VIDEO mode,<wbr/> if it is included in <a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a>,<wbr/>
+the HAL must list supported video size and fps range in
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/> For a given size,<wbr/> e.<wbr/>g.<wbr/>
+1280x720,<wbr/> if the HAL has two different sensor configurations for normal streaming
+mode and high speed streaming,<wbr/> when this scene mode is set/<wbr/>reset in a sequence of capture
+requests,<wbr/> the HAL may have to switch between different sensor modes.<wbr/>
+This mode is deprecated in HAL3.<wbr/>3,<wbr/> to support high speed video recording,<wbr/> please implement
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a> and CONSTRAINED_<wbr/>HIGH_<wbr/>SPEED_<wbr/>VIDEO
+capbility defined in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.videoStabilizationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Video stabilization is disabled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Video stabilization is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether video stabilization is
+active.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Video stabilization automatically warps images from
+the camera in order to stabilize motion between consecutive frames.<wbr/></p>
+<p>If enabled,<wbr/> video stabilization can modify the
+<a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> to keep the video stream stabilized.<wbr/></p>
+<p>Switching between different video stabilization modes may take several
+frames to initialize,<wbr/> the camera device will report the current mode
+in capture result metadata.<wbr/> For example,<wbr/> When "ON" mode is requested,<wbr/>
+the video stabilization modes in the first several capture results may
+still be "OFF",<wbr/> and it will become "ON" when the initialization is
+done.<wbr/></p>
+<p>In addition,<wbr/> not all recording sizes or frame rates may be supported for
+stabilization by a device that reports stabilization support.<wbr/> It is guaranteed
+that an output targeting a MediaRecorder or MediaCodec will be stabilized if
+the recording resolution is less than or equal to 1920 x 1080 (width less than
+or equal to 1920,<wbr/> height less than or equal to 1080),<wbr/> and the recording
+frame rate is less than or equal to 30fps.<wbr/>  At other sizes,<wbr/> the CaptureResult
+<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a> field will return
+OFF if the recording output is not stabilized,<wbr/> or if there are no output
+Surface types that can be stabilized.<wbr/></p>
+<p>If a camera device supports both this mode and OIS
+(<a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> turning both modes on may
+produce undesirable interaction,<wbr/> so it is recommended not to enable
+both at the same time.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.control.postRawSensitivityBoost">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.control.aeAvailableAntibandingModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Antibanding<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of auto-exposure antibanding modes for <a href="#controls_android.control.aeAntibandingMode">android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.aeAntibandingMode">android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not all of the auto-exposure anti-banding modes may be
+supported by a given camera device.<wbr/> This field lists the
+valid anti-banding modes that the application may request
+for this camera device with the
+<a href="#controls_android.control.aeAntibandingMode">android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode</a> control.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.aeAvailableModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of auto-exposure modes for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not all the auto-exposure modes may be supported by a
+given camera device,<wbr/> especially if no flash unit is
+available.<wbr/> This entry lists the valid modes for
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> for this camera device.<wbr/></p>
+<p>All camera devices support ON,<wbr/> and all camera devices with flash
+units support ON_<wbr/>AUTO_<wbr/>FLASH and ON_<wbr/>ALWAYS_<wbr/>FLASH.<wbr/></p>
+<p>FULL mode camera devices always support OFF mode,<wbr/>
+which enables application control of camera exposure time,<wbr/>
+sensitivity,<wbr/> and frame duration.<wbr/></p>
+<p>LEGACY mode camera devices never support OFF mode.<wbr/>
+LIMITED mode devices support OFF if they support the MANUAL_<wbr/>SENSOR
+capability.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.aeAvailableTargetFpsRanges">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Target<wbr/>Fps<wbr/>Ranges
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2 x n
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">list of pairs of frame rates</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of frame rate ranges for <a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a> supported by
+this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Frames per second (FPS)
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For devices at the LEGACY level or above:</p>
+<ul>
+<li>
+<p>For constant-framerate recording,<wbr/> for each normal
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/> that is,<wbr/> a
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#quality">quality</a> in
+the range [<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_LOW">QUALITY_<wbr/>LOW</a>,<wbr/>
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#QUALITY_2160P">QUALITY_<wbr/>2160P</a>],<wbr/> if the profile is
+supported by the device and has
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code>,<wbr/> this list will
+always include (<code>x</code>,<wbr/><code>x</code>).<wbr/></p>
+</li>
+<li>
+<p>Also,<wbr/> a camera device must either not support any
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a>,<wbr/>
+or support at least one
+normal <a href="https://developer.android.com/reference/android/media/CamcorderProfile.html">CamcorderProfile</a> that has
+<a href="https://developer.android.com/reference/android/media/CamcorderProfile.html#videoFrameRate">videoFrameRate</a> <code>x</code> &gt;= 24.<wbr/></p>
+</li>
+</ul>
+<p>For devices at the LIMITED level or above:</p>
+<ul>
+<li>For YUV_<wbr/>420_<wbr/>888 burst capture use case,<wbr/> this list will always include (<code>min</code>,<wbr/> <code>max</code>)
+and (<code>max</code>,<wbr/> <code>max</code>) where <code>min</code> &lt;= 15 and <code>max</code> = the maximum output frame rate of the
+maximum YUV_<wbr/>420_<wbr/>888 output size.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.aeCompensationRange">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum and minimum exposure compensation values for
+<a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a>,<wbr/> in counts of <a href="#static_android.control.aeCompensationStep">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step</a>,<wbr/>
+that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Range [0,<wbr/>0] indicates that exposure compensation is not supported.<wbr/></p>
+<p>For LIMITED and FULL devices,<wbr/> range must follow below requirements if exposure
+compensation is supported (<code>range != [0,<wbr/> 0]</code>):</p>
+<p><code>Min.<wbr/>exposure compensation * <a href="#static_android.control.aeCompensationStep">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step</a> &lt;= -2 EV</code></p>
+<p><code>Max.<wbr/>exposure compensation * <a href="#static_android.control.aeCompensationStep">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step</a> &gt;= 2 EV</code></p>
+<p>LEGACY devices may support a smaller range than this.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.aeCompensationStep">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Smallest step by which the exposure compensation
+can be changed.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Exposure Value (EV)
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is the unit for <a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a>.<wbr/> For example,<wbr/> if this key has
+a value of <code>1/<wbr/>2</code>,<wbr/> then a setting of <code>-2</code> for <a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a> means
+that the target EV offset for the auto-exposure routine is -1 EV.<wbr/></p>
+<p>One unit of EV compensation changes the brightness of the captured image by a factor
+of two.<wbr/> +1 EV doubles the image brightness,<wbr/> while -1 EV halves the image brightness.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This must be less than or equal to 1/<wbr/>2.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.afAvailableModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>af<wbr/>Available<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of auto-focus (AF) modes for <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not all the auto-focus modes may be supported by a
+given camera device.<wbr/> This entry lists the valid modes for
+<a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> for this camera device.<wbr/></p>
+<p>All LIMITED and FULL mode camera devices will support OFF mode,<wbr/> and all
+camera devices with adjustable focuser units
+(<code><a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> &gt; 0</code>) will support AUTO mode.<wbr/></p>
+<p>LEGACY devices will support OFF mode only if they support
+focusing to infinity (by also setting <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> to
+<code>0.<wbr/>0f</code>).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.availableEffects">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>available<wbr/>Effects
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums (android.<wbr/>control.<wbr/>effect<wbr/>Mode).<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of color effects for <a href="#controls_android.control.effectMode">android.<wbr/>control.<wbr/>effect<wbr/>Mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.effectMode">android.<wbr/>control.<wbr/>effect<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This list contains the color effect modes that can be applied to
+images produced by the camera device.<wbr/>
+Implementations are not expected to be consistent across all devices.<wbr/>
+If no color effect modes are available for a device,<wbr/> this will only list
+OFF.<wbr/></p>
+<p>A color effect will only be applied if
+<a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> != OFF.<wbr/>  OFF is always included in this list.<wbr/></p>
+<p>This control has no effect on the operation of other control routines such
+as auto-exposure,<wbr/> white balance,<wbr/> or focus.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.availableSceneModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums (android.<wbr/>control.<wbr/>scene<wbr/>Mode).<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of scene modes for <a href="#controls_android.control.sceneMode">android.<wbr/>control.<wbr/>scene<wbr/>Mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.sceneMode">android.<wbr/>control.<wbr/>scene<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This list contains scene modes that can be set for the camera device.<wbr/>
+Only scene modes that have been fully implemented for the
+camera device may be included here.<wbr/> Implementations are not expected
+to be consistent across all devices.<wbr/></p>
+<p>If no scene modes are supported by the camera device,<wbr/> this
+will be set to DISABLED.<wbr/> Otherwise DISABLED will not be listed.<wbr/></p>
+<p>FACE_<wbr/>PRIORITY is always listed if face detection is
+supported (i.<wbr/>e.<wbr/><code><a href="#static_android.statistics.info.maxFaceCount">android.<wbr/>statistics.<wbr/>info.<wbr/>max<wbr/>Face<wbr/>Count</a> &gt;
+0</code>).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.availableVideoStabilizationModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>available<wbr/>Video<wbr/>Stabilization<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of video stabilization modes for <a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a>
+that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>OFF will always be listed.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.awbAvailableModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Available<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of auto-white-balance modes for <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> that are supported by this
+camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not all the auto-white-balance modes may be supported by a
+given camera device.<wbr/> This entry lists the valid modes for
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> for this camera device.<wbr/></p>
+<p>All camera devices will support ON mode.<wbr/></p>
+<p>Camera devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability will always support OFF
+mode,<wbr/> which enables application control of white balance,<wbr/> by using
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a> and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a>(<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> must be set to TRANSFORM_<wbr/>MATRIX).<wbr/> This includes all FULL
+mode camera devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.maxRegions">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>control.<wbr/>max<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of the maximum number of regions that can be used for metering in
+auto-exposure (AE),<wbr/> auto-white balance (AWB),<wbr/> and auto-focus (AF);
+this corresponds to the the maximum number of elements in
+<a href="#controls_android.control.aeRegions">android.<wbr/>control.<wbr/>ae<wbr/>Regions</a>,<wbr/> <a href="#controls_android.control.awbRegions">android.<wbr/>control.<wbr/>awb<wbr/>Regions</a>,<wbr/>
+and <a href="#controls_android.control.afRegions">android.<wbr/>control.<wbr/>af<wbr/>Regions</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Value must be &gt;= 0 for each element.<wbr/> For full-capability devices
+this value must be &gt;= 1 for AE and AF.<wbr/> The order of the elements is:
+<code>(AE,<wbr/> AWB,<wbr/> AF)</code>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.maxRegionsAe">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Ae
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum number of metering regions that can be used by the auto-exposure (AE)
+routine.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Value will be &gt;= 0.<wbr/> For FULL-capability devices,<wbr/> this
+value will be &gt;= 1.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This corresponds to the the maximum allowed number of elements in
+<a href="#controls_android.control.aeRegions">android.<wbr/>control.<wbr/>ae<wbr/>Regions</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is private to the framework.<wbr/> Fill in
+maxRegions to have this entry be automatically populated.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.maxRegionsAwb">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Awb
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum number of metering regions that can be used by the auto-white balance (AWB)
+routine.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Value will be &gt;= 0.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This corresponds to the the maximum allowed number of elements in
+<a href="#controls_android.control.awbRegions">android.<wbr/>control.<wbr/>awb<wbr/>Regions</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is private to the framework.<wbr/> Fill in
+maxRegions to have this entry be automatically populated.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.maxRegionsAf">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Af
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum number of metering regions that can be used by the auto-focus (AF) routine.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Value will be &gt;= 0.<wbr/> For FULL-capability devices,<wbr/> this
+value will be &gt;= 1.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This corresponds to the the maximum allowed number of elements in
+<a href="#controls_android.control.afRegions">android.<wbr/>control.<wbr/>af<wbr/>Regions</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is private to the framework.<wbr/> Fill in
+maxRegions to have this entry be automatically populated.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.sceneModeOverrides">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>scene<wbr/>Mode<wbr/>Overrides
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x length(availableSceneModes)
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Ordered list of auto-exposure,<wbr/> auto-white balance,<wbr/> and auto-focus
+settings to use with each available scene mode.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>For each available scene mode,<wbr/> the list must contain three
+entries containing the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> values used
+by the camera device.<wbr/> The entry order is <code>(aeMode,<wbr/> awbMode,<wbr/> afMode)</code>
+where aeMode has the lowest index position.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When a scene mode is enabled,<wbr/> the camera device is expected
+to override <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/>
+and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> with its preferred settings for
+that scene mode.<wbr/></p>
+<p>The order of this list matches that of availableSceneModes,<wbr/>
+with 3 entries for each mode.<wbr/>  The overrides listed
+for FACE_<wbr/>PRIORITY and FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT (if supported) are ignored,<wbr/>
+since for that mode the application-set <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> values are
+used instead,<wbr/> matching the behavior when <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a>
+is set to AUTO.<wbr/> It is recommended that the FACE_<wbr/>PRIORITY and
+FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT (if supported) overrides should be set to 0.<wbr/></p>
+<p>For example,<wbr/> if availableSceneModes contains
+<code>(FACE_<wbr/>PRIORITY,<wbr/> ACTION,<wbr/> NIGHT)</code>,<wbr/>  then the camera framework
+expects sceneModeOverrides to have 9 entries formatted like:
+<code>(0,<wbr/> 0,<wbr/> 0,<wbr/> ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/> AUTO,<wbr/> CONTINUOUS_<wbr/>PICTURE,<wbr/>
+ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/> INCANDESCENT,<wbr/> AUTO)</code>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>To maintain backward compatibility,<wbr/> this list will be made available
+in the static metadata of the camera service.<wbr/>  The camera service will
+use these values to set <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> when using a scene
+mode other than FACE_<wbr/>PRIORITY and FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT (if supported).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.availableHighSpeedVideoConfigurations">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x n
+                </span>
+              <span class="entry_type_visibility"> [hidden as highSpeedVideoConfiguration]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of available high speed video size,<wbr/> fps range and max batch size configurations
+supported by the camera device,<wbr/> in the format of (width,<wbr/> height,<wbr/> fps_<wbr/>min,<wbr/> fps_<wbr/>max,<wbr/> batch_<wbr/>size_<wbr/>max).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>For each configuration,<wbr/> the fps_<wbr/>max &gt;= 120fps.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When CONSTRAINED_<wbr/>HIGH_<wbr/>SPEED_<wbr/>VIDEO is supported in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>,<wbr/>
+this metadata will list the supported high speed video size,<wbr/> fps range and max batch size
+configurations.<wbr/> All the sizes listed in this configuration will be a subset of the sizes
+reported by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes">StreamConfigurationMap#getOutputSizes</a>
+for processed non-stalling formats.<wbr/></p>
+<p>For the high speed video use case,<wbr/> the application must
+select the video size and fps range from this metadata to configure the recording and
+preview streams and setup the recording requests.<wbr/> For example,<wbr/> if the application intends
+to do high speed recording,<wbr/> it can select the maximum size reported by this metadata to
+configure output streams.<wbr/> Once the size is selected,<wbr/> application can filter this metadata
+by selected size and get the supported fps ranges,<wbr/> and use these fps ranges to setup the
+recording requests.<wbr/> Note that for the use case of multiple output streams,<wbr/> application
+must select one unique size from this metadata to use (e.<wbr/>g.,<wbr/> preview and recording streams
+must have the same size).<wbr/> Otherwise,<wbr/> the high speed capture session creation will fail.<wbr/></p>
+<p>The min and max fps will be multiple times of 30fps.<wbr/></p>
+<p>High speed video streaming extends significant performance pressue to camera hardware,<wbr/>
+to achieve efficient high speed streaming,<wbr/> the camera device may have to aggregate
+multiple frames together and send to camera device for processing where the request
+controls are same for all the frames in this batch.<wbr/> Max batch size indicates
+the max possible number of frames the camera device will group together for this high
+speed stream configuration.<wbr/> This max batch size will be used to generate a high speed
+recording request list by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraConstrainedHighSpeedCaptureSession.html#createHighSpeedRequestList">CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList</a>.<wbr/>
+The max batch size for each configuration will satisfy below conditions:</p>
+<ul>
+<li>Each max batch size will be a divisor of its corresponding fps_<wbr/>max /<wbr/> 30.<wbr/> For example,<wbr/>
+if max_<wbr/>fps is 300,<wbr/> max batch size will only be 1,<wbr/> 2,<wbr/> 5,<wbr/> or 10.<wbr/></li>
+<li>The camera device may choose smaller internal batch size for each configuration,<wbr/> but
+the actual batch size will be a divisor of max batch size.<wbr/> For example,<wbr/> if the max batch
+size is 8,<wbr/> the actual batch size used by camera device will only be 1,<wbr/> 2,<wbr/> 4,<wbr/> or 8.<wbr/></li>
+<li>The max batch size in each configuration entry must be no larger than 32.<wbr/></li>
+</ul>
+<p>The camera device doesn't have to support batch mode to achieve high speed video recording,<wbr/>
+in such case,<wbr/> batch_<wbr/>size_<wbr/>max will be reported as 1 in each configuration entry.<wbr/></p>
+<p>This fps ranges in this configuration list can only be used to create requests
+that are submitted to a high speed camera capture session created by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>.<wbr/>
+The fps ranges reported in this metadata must not be used to setup capture requests for
+normal capture session,<wbr/> or it will cause request error.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All the sizes listed in this configuration will be a subset of the sizes reported by
+<a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> for processed non-stalling output formats.<wbr/>
+Note that for all high speed video configurations,<wbr/> HAL must be able to support a minimum
+of two streams,<wbr/> though the application might choose to configure just one stream.<wbr/></p>
+<p>The HAL may support multiple sensor modes for high speed outputs,<wbr/> for example,<wbr/> 120fps
+sensor mode and 120fps recording,<wbr/> 240fps sensor mode for 240fps recording.<wbr/> The application
+usually starts preview first,<wbr/> then starts recording.<wbr/> To avoid sensor mode switch caused
+stutter when starting recording as much as possible,<wbr/> the application may want to ensure
+the same sensor mode is used for preview and recording.<wbr/> Therefore,<wbr/> The HAL must advertise
+the variable fps range [30,<wbr/> fps_<wbr/>max] for each fixed fps range in this configuration list.<wbr/>
+For example,<wbr/> if the HAL advertises [120,<wbr/> 120] and [240,<wbr/> 240],<wbr/> the HAL must also advertise
+[30,<wbr/> 120] and [30,<wbr/> 240] for each configuration.<wbr/> In doing so,<wbr/> if the application intends to
+do 120fps recording,<wbr/> it can select [30,<wbr/> 120] to start preview,<wbr/> and [120,<wbr/> 120] to start
+recording.<wbr/> For these variable fps ranges,<wbr/> it's up to the HAL to decide the actual fps
+values that are suitable for smooth preview streaming.<wbr/> If the HAL sees different max_<wbr/>fps
+values that fall into different sensor modes in a sequence of requests,<wbr/> the HAL must
+switch the sensor mode as quick as possible to minimize the mode switch caused stutter.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.aeLockAvailable">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Lock<wbr/>Available
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device supports <a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Devices with MANUAL_<wbr/>SENSOR capability or BURST_<wbr/>CAPTURE capability will always
+list <code>true</code>.<wbr/> This includes FULL devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.awbLockAvailable">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Lock<wbr/>Available
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device supports <a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Devices with MANUAL_<wbr/>POST_<wbr/>PROCESSING capability or BURST_<wbr/>CAPTURE capability will
+always list <code>true</code>.<wbr/> This includes FULL devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.availableModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>available<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums (android.<wbr/>control.<wbr/>mode).<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of control modes for <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This list contains control modes that can be set for the camera device.<wbr/>
+LEGACY mode devices will always support AUTO mode.<wbr/> LIMITED and FULL
+devices will always support OFF,<wbr/> AUTO modes.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.control.postRawSensitivityBoostRange">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+
+
+                <div class="entry_type_notes">Range of supported post RAW sensitivitiy boosts</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Range of boosts for <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> supported
+by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Devices support post RAW sensitivity boost  will advertise
+<a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> key for controling
+post RAW sensitivity boost.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>(100,<wbr/> 100)</code> in this key.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key is added in HAL3.<wbr/>4.<wbr/> For HAL3.<wbr/>3 or earlier devices,<wbr/> camera framework will
+generate this key as <code>(100,<wbr/> 100)</code> if device supports any of RAW output formats.<wbr/>
+All HAL3.<wbr/>4 and above devices should list this key if device supports any of RAW
+output formats.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.control.aePrecaptureId">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Id
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The ID sent with the latest
+CAMERA2_<wbr/>TRIGGER_<wbr/>PRECAPTURE_<wbr/>METERING call</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Must be 0 if no
+CAMERA2_<wbr/>TRIGGER_<wbr/>PRECAPTURE_<wbr/>METERING trigger received yet
+by HAL.<wbr/> Always updated even if AE algorithm ignores the
+trigger</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeAntibandingMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will not adjust exposure duration to
+avoid banding problems.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">50HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will adjust exposure duration to
+avoid banding problems with 50Hz illumination sources.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">60HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will adjust exposure duration to
+avoid banding problems with 60Hz illumination
+sources.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will automatically adapt its
+antibanding routine to the current illumination
+condition.<wbr/> This is the default mode if AUTO is
+available on given camera device.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired setting for the camera device's auto-exposure
+algorithm's antibanding compensation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeAvailableAntibandingModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Antibanding<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some kinds of lighting fixtures,<wbr/> such as some fluorescent
+lights,<wbr/> flicker at the rate of the power supply frequency
+(60Hz or 50Hz,<wbr/> depending on country).<wbr/> While this is
+typically not noticeable to a person,<wbr/> it can be visible to
+a camera device.<wbr/> If a camera sets its exposure time to the
+wrong value,<wbr/> the flicker may become visible in the
+viewfinder as flicker or in a final captured image,<wbr/> as a
+set of variable-brightness bands across the image.<wbr/></p>
+<p>Therefore,<wbr/> the auto-exposure routines of camera devices
+include antibanding routines that ensure that the chosen
+exposure value will not cause such banding.<wbr/> The choice of
+exposure time depends on the rate of flicker,<wbr/> which the
+camera device can detect automatically,<wbr/> or the expected
+rate can be selected by the application using this
+control.<wbr/></p>
+<p>A given camera device may not support all of the possible
+options for the antibanding mode.<wbr/> The
+<a href="#static_android.control.aeAvailableAntibandingModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Antibanding<wbr/>Modes</a> key contains
+the available modes for a given camera device.<wbr/></p>
+<p>AUTO mode is the default if it is available on given
+camera device.<wbr/> When AUTO mode is not available,<wbr/> the
+default will be either 50HZ or 60HZ,<wbr/> and both 50HZ
+and 60HZ will be available.<wbr/></p>
+<p>If manual exposure control is enabled (by setting
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> to OFF),<wbr/>
+then this setting has no effect,<wbr/> and the application must
+ensure it selects exposure times that do not cause banding
+issues.<wbr/> The <a href="#dynamic_android.statistics.sceneFlicker">android.<wbr/>statistics.<wbr/>scene<wbr/>Flicker</a> key can assist
+the application in this.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For all capture request templates,<wbr/> this field must be set
+to AUTO if AUTO mode is available.<wbr/> If AUTO is not available,<wbr/>
+the default must be either 50HZ or 60HZ,<wbr/> and both 50HZ and
+60HZ must be available.<wbr/></p>
+<p>If manual exposure control is enabled (by setting
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> to OFF),<wbr/>
+then the exposure values provided by the application must not be
+adjusted for antibanding.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeExposureCompensation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Adjustment to auto-exposure (AE) target image
+brightness.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Compensation steps
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeCompensationRange">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The adjustment is measured as a count of steps,<wbr/> with the
+step size defined by <a href="#static_android.control.aeCompensationStep">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Step</a> and the
+allowed range by <a href="#static_android.control.aeCompensationRange">android.<wbr/>control.<wbr/>ae<wbr/>Compensation<wbr/>Range</a>.<wbr/></p>
+<p>For example,<wbr/> if the exposure value (EV) step is 0.<wbr/>333,<wbr/> '6'
+will mean an exposure compensation of +2 EV; -3 will mean an
+exposure compensation of -1 EV.<wbr/> One EV represents a doubling
+of image brightness.<wbr/> Note that this control will only be
+effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>!=</code> OFF.<wbr/> This control
+will take effect even when <a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> <code>== true</code>.<wbr/></p>
+<p>In the event of exposure compensation value being changed,<wbr/> camera device
+may take several frames to reach the newly requested exposure target.<wbr/>
+During that time,<wbr/> <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> field will be in the SEARCHING
+state.<wbr/> Once the new exposure target is reached,<wbr/> <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> will
+change from SEARCHING to either CONVERGED,<wbr/> LOCKED (if AE lock is enabled),<wbr/> or
+FLASH_<wbr/>REQUIRED (if the scene is too dark for still capture).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeLock">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Auto-exposure lock is disabled; the AE algorithm
+is free to update its parameters.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Auto-exposure lock is enabled; the AE algorithm
+must not update the exposure and sensitivity parameters
+while the lock is active.<wbr/></p>
+<p><a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a> setting changes
+will still take effect while auto-exposure is locked.<wbr/></p>
+<p>Some rare LEGACY devices may not support
+this,<wbr/> in which case the value will always be overridden to OFF.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-exposure (AE) is currently locked to its latest
+calculated values.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to <code>true</code> (ON),<wbr/> the AE algorithm is locked to its latest parameters,<wbr/>
+and will not change exposure settings until the lock is set to <code>false</code> (OFF).<wbr/></p>
+<p>Note that even when AE is locked,<wbr/> the flash may be fired if
+the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is ON_<wbr/>AUTO_<wbr/>FLASH /<wbr/>
+ON_<wbr/>ALWAYS_<wbr/>FLASH /<wbr/> ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE.<wbr/></p>
+<p>When <a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a> is changed,<wbr/> even if the AE lock
+is ON,<wbr/> the camera device will still adjust its exposure value.<wbr/></p>
+<p>If AE precapture is triggered (see <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>)
+when AE is already locked,<wbr/> the camera device will not change the exposure time
+(<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>) and sensitivity (<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>)
+parameters.<wbr/> The flash may be fired if the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>
+is ON_<wbr/>AUTO_<wbr/>FLASH/<wbr/>ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE and the scene is too dark.<wbr/> If the
+<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is ON_<wbr/>ALWAYS_<wbr/>FLASH,<wbr/> the scene may become overexposed.<wbr/>
+Similarly,<wbr/> AE precapture trigger CANCEL has no effect when AE is already locked.<wbr/></p>
+<p>When an AE precapture sequence is triggered,<wbr/> AE unlock will not be able to unlock
+the AE if AE is locked by the camera device internally during precapture metering
+sequence In other words,<wbr/> submitting requests with AE unlock has no effect for an
+ongoing precapture metering sequence.<wbr/> Otherwise,<wbr/> the precapture metering sequence
+will never succeed in a sequence of preview requests where AE lock is always set
+to <code>false</code>.<wbr/></p>
+<p>Since the camera device has a pipeline of in-flight requests,<wbr/> the settings that
+get locked do not necessarily correspond to the settings that were present in the
+latest capture result received from the camera device,<wbr/> since additional captures
+and AE updates may have occurred even before the result was sent out.<wbr/> If an
+application is switching between automatic and manual control and wishes to eliminate
+any flicker during the switch,<wbr/> the following procedure is recommended:</p>
+<ol>
+<li>Starting in auto-AE mode:</li>
+<li>Lock AE</li>
+<li>Wait for the first result to be output that has the AE locked</li>
+<li>Copy exposure settings from that result into a request,<wbr/> set the request to manual AE</li>
+<li>Submit the capture request,<wbr/> proceed to run manual AE as desired.<wbr/></li>
+</ol>
+<p>See <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> for AE lock related state transition details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's autoexposure routine is disabled.<wbr/></p>
+<p>The application-selected <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> are used by the camera
+device,<wbr/> along with android.<wbr/>flash.<wbr/>* fields,<wbr/> if there's
+a flash unit for this camera device.<wbr/></p>
+<p>Note that auto-white balance (AWB) and auto-focus (AF)
+behavior is device dependent when AE is in OFF mode.<wbr/>
+To have consistent behavior across different devices,<wbr/>
+it is recommended to either set AWB and AF to OFF mode
+or lock AWB and AF before setting AE to OFF.<wbr/>
+See <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a>,<wbr/> and <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>
+for more details.<wbr/></p>
+<p>LEGACY devices do not support the OFF mode and will
+override attempts to use this value to ON.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's autoexposure routine is active,<wbr/>
+with no flash control.<wbr/></p>
+<p>The application's values for
+<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> are ignored.<wbr/> The
+application has control over the various
+android.<wbr/>flash.<wbr/>* fields.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_AUTO_FLASH</span>
+                    <span class="entry_type_enum_notes"><p>Like ON,<wbr/> except that the camera device also controls
+the camera's flash unit,<wbr/> firing it in low-light
+conditions.<wbr/></p>
+<p>The flash may be fired during a precapture sequence
+(triggered by <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>) and
+may be fired for captures for which the
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> field is set to
+STILL_<wbr/>CAPTURE</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_ALWAYS_FLASH</span>
+                    <span class="entry_type_enum_notes"><p>Like ON,<wbr/> except that the camera device also controls
+the camera's flash unit,<wbr/> always firing it for still
+captures.<wbr/></p>
+<p>The flash may be fired during a precapture sequence
+(triggered by <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>) and
+will always be fired for captures for which the
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> field is set to
+STILL_<wbr/>CAPTURE</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON_AUTO_FLASH_REDEYE</span>
+                    <span class="entry_type_enum_notes"><p>Like ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/> but with automatic red eye
+reduction.<wbr/></p>
+<p>If deemed necessary by the camera device,<wbr/> a red eye
+reduction flash will fire during the precapture
+sequence.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired mode for the camera device's
+auto-exposure routine.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.aeAvailableModes">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is
+AUTO.<wbr/></p>
+<p>When set to any of the ON modes,<wbr/> the camera device's
+auto-exposure routine is enabled,<wbr/> overriding the
+application's selected exposure time,<wbr/> sensor sensitivity,<wbr/>
+and frame duration (<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>).<wbr/> If one of the FLASH modes
+is selected,<wbr/> the camera device's flash unit controls are
+also overridden.<wbr/></p>
+<p>The FLASH modes are only available if the camera device
+has a flash unit (<a href="#static_android.flash.info.available">android.<wbr/>flash.<wbr/>info.<wbr/>available</a> is <code>true</code>).<wbr/></p>
+<p>If flash TORCH mode is desired,<wbr/> this field must be set to
+ON or OFF,<wbr/> and <a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> set to TORCH.<wbr/></p>
+<p>When set to any of the ON modes,<wbr/> the values chosen by the
+camera device auto-exposure routine for the overridden
+fields for a given capture will be available in its
+CaptureResult.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-exposure adjustment.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAe">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Ae</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of regions supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAe">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Ae</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must be within <code>[0,<wbr/> 1000]</code>,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other exposure metering regions,<wbr/> so if only one
+region is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with 0
+weight is ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/>  If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeTargetFpsRange">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Range over which the auto-exposure routine can
+adjust the capture frame rate to maintain good
+exposure.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Frames per second (FPS)
+            </td>
+
+            <td class="entry_range">
+              <p>Any of the entries in <a href="#static_android.control.aeAvailableTargetFpsRanges">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Target<wbr/>Fps<wbr/>Ranges</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only constrains auto-exposure (AE) algorithm,<wbr/> not
+manual control of <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a> and
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aePrecaptureTrigger">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">IDLE</span>
+                    <span class="entry_type_enum_notes"><p>The trigger is idle.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">START</span>
+                    <span class="entry_type_enum_notes"><p>The precapture metering sequence will be started
+by the camera device.<wbr/></p>
+<p>The exact effect of the precapture trigger depends on
+the current AE mode and state.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANCEL</span>
+                    <span class="entry_type_enum_notes"><p>The camera device will cancel any currently active or completed
+precapture metering sequence,<wbr/> the auto-exposure routine will return to its
+initial state.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will trigger a precapture
+metering sequence when it processes this request.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is normally set to IDLE,<wbr/> or is not
+included at all in the request settings.<wbr/> When included and
+set to START,<wbr/> the camera device will trigger the auto-exposure (AE)
+precapture metering sequence.<wbr/></p>
+<p>When set to CANCEL,<wbr/> the camera device will cancel any active
+precapture metering trigger,<wbr/> and return to its initial AE state.<wbr/>
+If a precapture metering sequence is already completed,<wbr/> and the camera
+device has implicitly locked the AE for subsequent still capture,<wbr/> the
+CANCEL trigger will unlock the AE and return to its initial AE state.<wbr/></p>
+<p>The precapture sequence should be triggered before starting a
+high-quality still capture for final metering decisions to
+be made,<wbr/> and for firing pre-capture flash pulses to estimate
+scene brightness and required final capture flash power,<wbr/> when
+the flash is enabled.<wbr/></p>
+<p>Normally,<wbr/> this entry should be set to START for only a
+single request,<wbr/> and the application should wait until the
+sequence completes before starting a new one.<wbr/></p>
+<p>When a precapture metering sequence is finished,<wbr/> the camera device
+may lock the auto-exposure routine internally to be able to accurately expose the
+subsequent still capture image (<code><a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> == STILL_<wbr/>CAPTURE</code>).<wbr/>
+For this case,<wbr/> the AE may not resume normal scan if no subsequent still capture is
+submitted.<wbr/> To ensure that the AE routine restarts normal scan,<wbr/> the application should
+submit a request with <code><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> == true</code>,<wbr/> followed by a request
+with <code><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> == false</code>,<wbr/> if the application decides not to submit a
+still capture request after the precapture sequence completes.<wbr/> Alternatively,<wbr/> for
+API level 23 or newer devices,<wbr/> the CANCEL can be used to unlock the camera device
+internally locked AE if the application doesn't submit a still capture request after
+the AE precapture trigger.<wbr/> Note that,<wbr/> the CANCEL was added in API level 23,<wbr/> and must not
+be used in devices that have earlier API levels.<wbr/></p>
+<p>The exact effect of auto-exposure (AE) precapture trigger
+depends on the current AE mode and state; see
+<a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> for AE precapture state transition
+details.<wbr/></p>
+<p>On LEGACY-level devices,<wbr/> the precapture trigger is not supported;
+capturing a high-resolution JPEG image will automatically trigger a
+precapture sequence before the high-resolution capture,<wbr/> including
+potentially firing a pre-capture flash.<wbr/></p>
+<p>Using the precapture trigger and the auto-focus trigger <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>
+simultaneously is allowed.<wbr/> However,<wbr/> since these triggers often require cooperation between
+the auto-focus and auto-exposure routines (for example,<wbr/> the may need to be enabled for a
+focus sweep),<wbr/> the camera device may delay acting on a later trigger until the previous
+trigger has been fully handled.<wbr/> This may lead to longer intervals between the trigger and
+changes to <a href="#dynamic_android.control.aeState">android.<wbr/>control.<wbr/>ae<wbr/>State</a> indicating the start of the precapture sequence,<wbr/> for
+example.<wbr/></p>
+<p>If both the precapture and the auto-focus trigger are activated on the same request,<wbr/> then
+the camera device will complete them in the optimal order for that device.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must support triggering the AE precapture trigger while an AF trigger is active
+(and vice versa),<wbr/> or at the same time as the AF trigger.<wbr/>  It is acceptable for the HAL to
+treat these as two consecutive triggers,<wbr/> for example handling the AF trigger and then the
+AE trigger.<wbr/>  Or the HAL may choose to optimize the case with both triggers fired at once,<wbr/>
+to minimize the latency for converging both focus and exposure/<wbr/>flash usage.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.aeState">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>ae<wbr/>State
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">INACTIVE</span>
+                    <span class="entry_type_enum_notes"><p>AE is off or recently reset.<wbr/></p>
+<p>When a camera device is opened,<wbr/> it starts in
+this state.<wbr/> This is a transient state,<wbr/> the camera device may skip reporting
+this state in capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SEARCHING</span>
+                    <span class="entry_type_enum_notes"><p>AE doesn't yet have a good set of control values
+for the current scene.<wbr/></p>
+<p>This is a transient state,<wbr/> the camera device may skip
+reporting this state in capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONVERGED</span>
+                    <span class="entry_type_enum_notes"><p>AE has a good set of control values for the
+current scene.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">LOCKED</span>
+                    <span class="entry_type_enum_notes"><p>AE has been locked.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FLASH_REQUIRED</span>
+                    <span class="entry_type_enum_notes"><p>AE has a good set of control values,<wbr/> but flash
+needs to be fired for good quality still
+capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PRECAPTURE</span>
+                    <span class="entry_type_enum_notes"><p>AE has been asked to do a precapture sequence
+and is currently executing it.<wbr/></p>
+<p>Precapture can be triggered through setting
+<a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> to START.<wbr/> Currently
+active and completed (if it causes camera device internal AE lock) precapture
+metering sequence can be canceled through setting
+<a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> to CANCEL.<wbr/></p>
+<p>Once PRECAPTURE completes,<wbr/> AE will transition to CONVERGED
+or FLASH_<wbr/>REQUIRED as appropriate.<wbr/> This is a transient
+state,<wbr/> the camera device may skip reporting this state in
+capture result.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Current state of the auto-exposure (AE) algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Switching between or enabling AE modes (<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>) always
+resets the AE state to INACTIVE.<wbr/> Similarly,<wbr/> switching between <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a>,<wbr/>
+or <a href="#controls_android.control.sceneMode">android.<wbr/>control.<wbr/>scene<wbr/>Mode</a> if <code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == USE_<wbr/>SCENE_<wbr/>MODE</code> resets all
+the algorithm states to INACTIVE.<wbr/></p>
+<p>The camera device can do several state transitions between two results,<wbr/> if it is
+allowed by the state transition table.<wbr/> For example: INACTIVE may never actually be
+seen in a result.<wbr/></p>
+<p>The state in the result is the state for this image (in sync with this image): if
+AE state becomes CONVERGED,<wbr/> then the image data associated with this result should
+be good to use.<wbr/></p>
+<p>Below are state transition tables for different AE modes.<wbr/></p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center"></td>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device auto exposure algorithm is disabled</td>
+</tr>
+</tbody>
+</table>
+<p>When <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is AE_<wbr/>MODE_<wbr/>ON_<wbr/>*:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device initiates AE scan</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values changing</td>
+</tr>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">SEARCHING</td>
+<td align="center">Camera device finishes AE scan</td>
+<td align="center">CONVERGED</td>
+<td align="center">Good values,<wbr/> not changing</td>
+</tr>
+<tr>
+<td align="center">SEARCHING</td>
+<td align="center">Camera device finishes AE scan</td>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Converged but too dark w/<wbr/>o flash</td>
+</tr>
+<tr>
+<td align="center">SEARCHING</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">CONVERGED</td>
+<td align="center">Camera device initiates AE scan</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values changing</td>
+</tr>
+<tr>
+<td align="center">CONVERGED</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Camera device initiates AE scan</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values changing</td>
+</tr>
+<tr>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is OFF</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values not good after unlock</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is OFF</td>
+<td align="center">CONVERGED</td>
+<td align="center">Values good after unlock</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center"><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is OFF</td>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Exposure good,<wbr/> but too dark</td>
+</tr>
+<tr>
+<td align="center">PRECAPTURE</td>
+<td align="center">Sequence done.<wbr/> <a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is OFF</td>
+<td align="center">CONVERGED</td>
+<td align="center">Ready for high-quality capture</td>
+</tr>
+<tr>
+<td align="center">PRECAPTURE</td>
+<td align="center">Sequence done.<wbr/> <a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Ready for high-quality capture</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center">aeLock is ON and aePrecaptureTrigger is START</td>
+<td align="center">LOCKED</td>
+<td align="center">Precapture trigger is ignored when AE is already locked</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center">aeLock is ON and aePrecaptureTrigger is CANCEL</td>
+<td align="center">LOCKED</td>
+<td align="center">Precapture trigger is ignored when AE is already locked</td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is START</td>
+<td align="center">PRECAPTURE</td>
+<td align="center">Start AE precapture metering sequence</td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Currently active precapture metering sequence is canceled</td>
+</tr>
+</tbody>
+</table>
+<p>For the above table,<wbr/> the camera device may skip reporting any state changes that happen
+without application intervention (i.<wbr/>e.<wbr/> mode switch,<wbr/> trigger,<wbr/> locking).<wbr/> Any state that
+can be skipped in that manner is called a transient state.<wbr/></p>
+<p>For example,<wbr/> for above AE modes (AE_<wbr/>MODE_<wbr/>ON_<wbr/>*),<wbr/> in addition to the state transitions
+listed in above table,<wbr/> it is also legal for the camera device to skip one or more
+transient states between two results.<wbr/> See below table for examples:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device finished AE scan</td>
+<td align="center">CONVERGED</td>
+<td align="center">Values are already good,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is START,<wbr/> sequence done</td>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Converged but too dark w/<wbr/>o flash after a precapture sequence,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is START,<wbr/> sequence done</td>
+<td align="center">CONVERGED</td>
+<td align="center">Converged after a precapture sequence,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is CANCEL,<wbr/> converged</td>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Converged but too dark w/<wbr/>o flash after a precapture sequence is canceled,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">Any state (excluding LOCKED)</td>
+<td align="center"><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is CANCEL,<wbr/> converged</td>
+<td align="center">CONVERGED</td>
+<td align="center">Converged after a precapture sequenceis canceled,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">CONVERGED</td>
+<td align="center">Camera device finished AE scan</td>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Converged but too dark w/<wbr/>o flash after a new scan,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">FLASH_<wbr/>REQUIRED</td>
+<td align="center">Camera device finished AE scan</td>
+<td align="center">CONVERGED</td>
+<td align="center">Converged after a new scan,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+</tbody>
+</table>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.afMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The auto-focus routine does not control the lens;
+<a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> is controlled by the
+application.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>Basic automatic focus mode.<wbr/></p>
+<p>In this mode,<wbr/> the lens does not move unless
+the autofocus trigger action is called.<wbr/> When that trigger
+is activated,<wbr/> AF will transition to ACTIVE_<wbr/>SCAN,<wbr/> then to
+the outcome of the scan (FOCUSED or NOT_<wbr/>FOCUSED).<wbr/></p>
+<p>Always supported if lens is not fixed focus.<wbr/></p>
+<p>Use <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> to determine if lens
+is fixed-focus.<wbr/></p>
+<p>Triggering AF_<wbr/>CANCEL resets the lens position to default,<wbr/>
+and sets the AF state to INACTIVE.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MACRO</span>
+                    <span class="entry_type_enum_notes"><p>Close-up focusing mode.<wbr/></p>
+<p>In this mode,<wbr/> the lens does not move unless the
+autofocus trigger action is called.<wbr/> When that trigger is
+activated,<wbr/> AF will transition to ACTIVE_<wbr/>SCAN,<wbr/> then to
+the outcome of the scan (FOCUSED or NOT_<wbr/>FOCUSED).<wbr/> This
+mode is optimized for focusing on objects very close to
+the camera.<wbr/></p>
+<p>When that trigger is activated,<wbr/> AF will transition to
+ACTIVE_<wbr/>SCAN,<wbr/> then to the outcome of the scan (FOCUSED or
+NOT_<wbr/>FOCUSED).<wbr/> Triggering cancel AF resets the lens
+position to default,<wbr/> and sets the AF state to
+INACTIVE.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONTINUOUS_VIDEO</span>
+                    <span class="entry_type_enum_notes"><p>In this mode,<wbr/> the AF algorithm modifies the lens
+position continually to attempt to provide a
+constantly-in-focus image stream.<wbr/></p>
+<p>The focusing behavior should be suitable for good quality
+video recording; typically this means slower focus
+movement and no overshoots.<wbr/> When the AF trigger is not
+involved,<wbr/> the AF algorithm should start in INACTIVE state,<wbr/>
+and then transition into PASSIVE_<wbr/>SCAN and PASSIVE_<wbr/>FOCUSED
+states as appropriate.<wbr/> When the AF trigger is activated,<wbr/>
+the algorithm should immediately transition into
+AF_<wbr/>FOCUSED or AF_<wbr/>NOT_<wbr/>FOCUSED as appropriate,<wbr/> and lock the
+lens position until a cancel AF trigger is received.<wbr/></p>
+<p>Once cancel is received,<wbr/> the algorithm should transition
+back to INACTIVE and resume passive scan.<wbr/> Note that this
+behavior is not identical to CONTINUOUS_<wbr/>PICTURE,<wbr/> since an
+ongoing PASSIVE_<wbr/>SCAN must immediately be
+canceled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONTINUOUS_PICTURE</span>
+                    <span class="entry_type_enum_notes"><p>In this mode,<wbr/> the AF algorithm modifies the lens
+position continually to attempt to provide a
+constantly-in-focus image stream.<wbr/></p>
+<p>The focusing behavior should be suitable for still image
+capture; typically this means focusing as fast as
+possible.<wbr/> When the AF trigger is not involved,<wbr/> the AF
+algorithm should start in INACTIVE state,<wbr/> and then
+transition into PASSIVE_<wbr/>SCAN and PASSIVE_<wbr/>FOCUSED states as
+appropriate as it attempts to maintain focus.<wbr/> When the AF
+trigger is activated,<wbr/> the algorithm should finish its
+PASSIVE_<wbr/>SCAN if active,<wbr/> and then transition into
+AF_<wbr/>FOCUSED or AF_<wbr/>NOT_<wbr/>FOCUSED as appropriate,<wbr/> and lock the
+lens position until a cancel AF trigger is received.<wbr/></p>
+<p>When the AF cancel trigger is activated,<wbr/> the algorithm
+should transition back to INACTIVE and then act as if it
+has just been started.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">EDOF</span>
+                    <span class="entry_type_enum_notes"><p>Extended depth of field (digital focus) mode.<wbr/></p>
+<p>The camera device will produce images with an extended
+depth of field automatically; no special focusing
+operations need to be done before taking a picture.<wbr/></p>
+<p>AF triggers are ignored,<wbr/> and the AF state will always be
+INACTIVE.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-focus (AF) is currently enabled,<wbr/> and what
+mode it is set to.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.afAvailableModes">android.<wbr/>control.<wbr/>af<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> = AUTO and the lens is not fixed focus
+(i.<wbr/>e.<wbr/> <code><a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> &gt; 0</code>).<wbr/> Also note that
+when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is OFF,<wbr/> the behavior of AF is device
+dependent.<wbr/> It is recommended to lock AF by using <a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a> before
+setting <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> to OFF,<wbr/> or set AF mode to OFF when AE is OFF.<wbr/></p>
+<p>If the lens is controlled by the camera device auto-focus algorithm,<wbr/>
+the camera device will report the current AF status in <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a>
+in result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When afMode is AUTO or MACRO,<wbr/> the lens must not move until an AF trigger is sent in a
+request (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a> <code>==</code> START).<wbr/> After an AF trigger,<wbr/> the afState will end
+up with either FOCUSED_<wbr/>LOCKED or NOT_<wbr/>FOCUSED_<wbr/>LOCKED state (see
+<a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for detailed state transitions),<wbr/> which indicates that the lens is
+locked and will not move.<wbr/> If camera movement (e.<wbr/>g.<wbr/> tilting camera) causes the lens to move
+after the lens is locked,<wbr/> the HAL must compensate this movement appropriately such that
+the same focal plane remains in focus.<wbr/></p>
+<p>When afMode is one of the continuous auto focus modes,<wbr/> the HAL is free to start a AF
+scan whenever it's not locked.<wbr/> When the lens is locked after an AF trigger
+(see <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for detailed state transitions),<wbr/> the HAL should maintain the
+same lock behavior as above.<wbr/></p>
+<p>When afMode is OFF,<wbr/> the application controls focus manually.<wbr/> The accuracy of the
+focus distance control depends on the <a href="#static_android.lens.info.focusDistanceCalibration">android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration</a>.<wbr/>
+However,<wbr/> the lens must not move regardless of the camera movement for any focus distance
+manual control.<wbr/></p>
+<p>To put this in concrete terms,<wbr/> if the camera has lens elements which may move based on
+camera orientation or motion (e.<wbr/>g.<wbr/> due to gravity),<wbr/> then the HAL must drive the lens to
+remain in a fixed position invariant to the camera's orientation or motion,<wbr/> for example,<wbr/>
+by using accelerometer measurements in the lens control logic.<wbr/> This is a typical issue
+that will arise on camera modules with open-loop VCMs.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.afRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-focus.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAf">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Af</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of focus areas supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAf">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Af</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must be within <code>[0,<wbr/> 1000]</code>,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other metering regions,<wbr/> so if only one region
+is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with 0 weight is
+ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/> If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.afTrigger">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>af<wbr/>Trigger
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">IDLE</span>
+                    <span class="entry_type_enum_notes"><p>The trigger is idle.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">START</span>
+                    <span class="entry_type_enum_notes"><p>Autofocus will trigger now.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANCEL</span>
+                    <span class="entry_type_enum_notes"><p>Autofocus will return to its initial
+state,<wbr/> and cancel any currently active trigger.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will trigger autofocus for this request.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is normally set to IDLE,<wbr/> or is not
+included at all in the request settings.<wbr/></p>
+<p>When included and set to START,<wbr/> the camera device will trigger the
+autofocus algorithm.<wbr/> If autofocus is disabled,<wbr/> this trigger has no effect.<wbr/></p>
+<p>When set to CANCEL,<wbr/> the camera device will cancel any active trigger,<wbr/>
+and return to its initial AF state.<wbr/></p>
+<p>Generally,<wbr/> applications should set this entry to START or CANCEL for only a
+single capture,<wbr/> and then return it to IDLE (or not set at all).<wbr/> Specifying
+START for multiple captures in a row means restarting the AF operation over
+and over again.<wbr/></p>
+<p>See <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a> for what the trigger means for each AF mode.<wbr/></p>
+<p>Using the autofocus trigger and the precapture trigger <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>
+simultaneously is allowed.<wbr/> However,<wbr/> since these triggers often require cooperation between
+the auto-focus and auto-exposure routines (for example,<wbr/> the may need to be enabled for a
+focus sweep),<wbr/> the camera device may delay acting on a later trigger until the previous
+trigger has been fully handled.<wbr/> This may lead to longer intervals between the trigger and
+changes to <a href="#dynamic_android.control.afState">android.<wbr/>control.<wbr/>af<wbr/>State</a>,<wbr/> for example.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must support triggering the AF trigger while an AE precapture trigger is active
+(and vice versa),<wbr/> or at the same time as the AE trigger.<wbr/>  It is acceptable for the HAL to
+treat these as two consecutive triggers,<wbr/> for example handling the AF trigger and then the
+AE trigger.<wbr/>  Or the HAL may choose to optimize the case with both triggers fired at once,<wbr/>
+to minimize the latency for converging both focus and exposure/<wbr/>flash usage.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.afState">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>af<wbr/>State
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">INACTIVE</span>
+                    <span class="entry_type_enum_notes"><p>AF is off or has not yet tried to scan/<wbr/>been asked
+to scan.<wbr/></p>
+<p>When a camera device is opened,<wbr/> it starts in this
+state.<wbr/> This is a transient state,<wbr/> the camera device may
+skip reporting this state in capture
+result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PASSIVE_SCAN</span>
+                    <span class="entry_type_enum_notes"><p>AF is currently performing an AF scan initiated the
+camera device in a continuous autofocus mode.<wbr/></p>
+<p>Only used by CONTINUOUS_<wbr/>* AF modes.<wbr/> This is a transient
+state,<wbr/> the camera device may skip reporting this state in
+capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PASSIVE_FOCUSED</span>
+                    <span class="entry_type_enum_notes"><p>AF currently believes it is in focus,<wbr/> but may
+restart scanning at any time.<wbr/></p>
+<p>Only used by CONTINUOUS_<wbr/>* AF modes.<wbr/> This is a transient
+state,<wbr/> the camera device may skip reporting this state in
+capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ACTIVE_SCAN</span>
+                    <span class="entry_type_enum_notes"><p>AF is performing an AF scan because it was
+triggered by AF trigger.<wbr/></p>
+<p>Only used by AUTO or MACRO AF modes.<wbr/> This is a transient
+state,<wbr/> the camera device may skip reporting this state in
+capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FOCUSED_LOCKED</span>
+                    <span class="entry_type_enum_notes"><p>AF believes it is focused correctly and has locked
+focus.<wbr/></p>
+<p>This state is reached only after an explicit START AF trigger has been
+sent (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>),<wbr/> when good focus has been obtained.<wbr/></p>
+<p>The lens will remain stationary until the AF mode (<a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>) is changed or
+a new AF trigger is sent to the camera device (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NOT_FOCUSED_LOCKED</span>
+                    <span class="entry_type_enum_notes"><p>AF has failed to focus successfully and has locked
+focus.<wbr/></p>
+<p>This state is reached only after an explicit START AF trigger has been
+sent (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>),<wbr/> when good focus cannot be obtained.<wbr/></p>
+<p>The lens will remain stationary until the AF mode (<a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>) is changed or
+a new AF trigger is sent to the camera device (<a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a>).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PASSIVE_UNFOCUSED</span>
+                    <span class="entry_type_enum_notes"><p>AF finished a passive scan without finding focus,<wbr/>
+and may restart scanning at any time.<wbr/></p>
+<p>Only used by CONTINUOUS_<wbr/>* AF modes.<wbr/> This is a transient state,<wbr/> the camera
+device may skip reporting this state in capture result.<wbr/></p>
+<p>LEGACY camera devices do not support this state.<wbr/> When a passive
+scan has finished,<wbr/> it will always go to PASSIVE_<wbr/>FOCUSED.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Current state of auto-focus (AF) algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Switching between or enabling AF modes (<a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>) always
+resets the AF state to INACTIVE.<wbr/> Similarly,<wbr/> switching between <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a>,<wbr/>
+or <a href="#controls_android.control.sceneMode">android.<wbr/>control.<wbr/>scene<wbr/>Mode</a> if <code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == USE_<wbr/>SCENE_<wbr/>MODE</code> resets all
+the algorithm states to INACTIVE.<wbr/></p>
+<p>The camera device can do several state transitions between two results,<wbr/> if it is
+allowed by the state transition table.<wbr/> For example: INACTIVE may never actually be
+seen in a result.<wbr/></p>
+<p>The state in the result is the state for this image (in sync with this image): if
+AF state becomes FOCUSED,<wbr/> then the image data associated with this result should
+be sharp.<wbr/></p>
+<p>Below are state transition tables for different AF modes.<wbr/></p>
+<p>When <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> is AF_<wbr/>MODE_<wbr/>OFF or AF_<wbr/>MODE_<wbr/>EDOF:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center"></td>
+<td align="center">INACTIVE</td>
+<td align="center">Never changes</td>
+</tr>
+</tbody>
+</table>
+<p>When <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> is AF_<wbr/>MODE_<wbr/>AUTO or AF_<wbr/>MODE_<wbr/>MACRO:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">Start AF sweep,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">AF sweep done</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Focused,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">AF sweep done</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Not focused,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Cancel/<wbr/>reset AF,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Cancel/<wbr/>reset AF</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">Start new sweep,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Cancel/<wbr/>reset AF</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">ACTIVE_<wbr/>SCAN</td>
+<td align="center">Start new sweep,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">Any state</td>
+<td align="center">Mode change</td>
+<td align="center">INACTIVE</td>
+<td align="center"></td>
+</tr>
+</tbody>
+</table>
+<p>For the above table,<wbr/> the camera device may skip reporting any state changes that happen
+without application intervention (i.<wbr/>e.<wbr/> mode switch,<wbr/> trigger,<wbr/> locking).<wbr/> Any state that
+can be skipped in that manner is called a transient state.<wbr/></p>
+<p>For example,<wbr/> for these AF modes (AF_<wbr/>MODE_<wbr/>AUTO and AF_<wbr/>MODE_<wbr/>MACRO),<wbr/> in addition to the
+state transitions listed in above table,<wbr/> it is also legal for the camera device to skip
+one or more transient states between two results.<wbr/> See below table for examples:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Focus is already good or good after a scan,<wbr/> lens is now locked.<wbr/></td>
+</tr>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Focus failed after a scan,<wbr/> lens is now locked.<wbr/></td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Focus is already good or good after a scan,<wbr/> lens is now locked.<wbr/></td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Focus is good after a scan,<wbr/> lens is not locked.<wbr/></td>
+</tr>
+</tbody>
+</table>
+<p>When <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> is AF_<wbr/>MODE_<wbr/>CONTINUOUS_<wbr/>VIDEO:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF state query,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Camera device completes current scan</td>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">End AF scan,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Camera device fails current scan</td>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">End AF scan,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate transition,<wbr/> if focus is good.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate transition,<wbr/> if focus is bad.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Reset lens position,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate transition,<wbr/> lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate transition,<wbr/> lens now locked</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">No effect</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Restart AF scan</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">No effect</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Restart AF scan</td>
+</tr>
+</tbody>
+</table>
+<p>When <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> is AF_<wbr/>MODE_<wbr/>CONTINUOUS_<wbr/>PICTURE:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF state query,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Camera device completes current scan</td>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">End AF scan,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Camera device fails current scan</td>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">End AF scan,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Eventual transition once the focus is good.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Eventual transition if cannot find focus.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Reset lens position,<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">Camera device initiates new scan</td>
+<td align="center">PASSIVE_<wbr/>SCAN</td>
+<td align="center">Start AF scan,<wbr/> Lens now moving</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>FOCUSED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate trans.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">PASSIVE_<wbr/>UNFOCUSED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">Immediate trans.<wbr/> Lens now locked</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">No effect</td>
+</tr>
+<tr>
+<td align="center">FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Restart AF scan</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>TRIGGER</td>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">No effect</td>
+</tr>
+<tr>
+<td align="center">NOT_<wbr/>FOCUSED_<wbr/>LOCKED</td>
+<td align="center">AF_<wbr/>CANCEL</td>
+<td align="center">INACTIVE</td>
+<td align="center">Restart AF scan</td>
+</tr>
+</tbody>
+</table>
+<p>When switch between AF_<wbr/>MODE_<wbr/>CONTINUOUS_<wbr/>* (CAF modes) and AF_<wbr/>MODE_<wbr/>AUTO/<wbr/>AF_<wbr/>MODE_<wbr/>MACRO
+(AUTO modes),<wbr/> the initial INACTIVE or PASSIVE_<wbr/>SCAN states may be skipped by the
+camera device.<wbr/> When a trigger is included in a mode switch request,<wbr/> the trigger
+will be evaluated in the context of the new mode in the request.<wbr/>
+See below table for examples:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">any state</td>
+<td align="center">CAF--&gt;AUTO mode switch</td>
+<td align="center">INACTIVE</td>
+<td align="center">Mode switch without trigger,<wbr/> initial state must be INACTIVE</td>
+</tr>
+<tr>
+<td align="center">any state</td>
+<td align="center">CAF--&gt;AUTO mode switch with AF_<wbr/>TRIGGER</td>
+<td align="center">trigger-reachable states from INACTIVE</td>
+<td align="center">Mode switch with trigger,<wbr/> INACTIVE is skipped</td>
+</tr>
+<tr>
+<td align="center">any state</td>
+<td align="center">AUTO--&gt;CAF mode switch</td>
+<td align="center">passively reachable states from INACTIVE</td>
+<td align="center">Mode switch without trigger,<wbr/> passive transient state is skipped</td>
+</tr>
+</tbody>
+</table>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.afTriggerId">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>af<wbr/>Trigger<wbr/>Id
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The ID sent with the latest
+CAMERA2_<wbr/>TRIGGER_<wbr/>AUTOFOCUS call</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Must be 0 if no CAMERA2_<wbr/>TRIGGER_<wbr/>AUTOFOCUS trigger
+received yet by HAL.<wbr/> Always updated even if AF algorithm
+ignores the trigger</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.awbLock">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Auto-white balance lock is disabled; the AWB
+algorithm is free to update its parameters if in AUTO
+mode.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Auto-white balance lock is enabled; the AWB
+algorithm will not update its parameters while the lock
+is active.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-white balance (AWB) is currently locked to its
+latest calculated values.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to <code>true</code> (ON),<wbr/> the AWB algorithm is locked to its latest parameters,<wbr/>
+and will not change color balance settings until the lock is set to <code>false</code> (OFF).<wbr/></p>
+<p>Since the camera device has a pipeline of in-flight requests,<wbr/> the settings that
+get locked do not necessarily correspond to the settings that were present in the
+latest capture result received from the camera device,<wbr/> since additional captures
+and AWB updates may have occurred even before the result was sent out.<wbr/> If an
+application is switching between automatic and manual control and wishes to eliminate
+any flicker during the switch,<wbr/> the following procedure is recommended:</p>
+<ol>
+<li>Starting in auto-AWB mode:</li>
+<li>Lock AWB</li>
+<li>Wait for the first result to be output that has the AWB locked</li>
+<li>Copy AWB settings from that result into a request,<wbr/> set the request to manual AWB</li>
+<li>Submit the capture request,<wbr/> proceed to run manual AWB as desired.<wbr/></li>
+</ol>
+<p>Note that AWB lock is only meaningful when
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> is in the AUTO mode; in other modes,<wbr/>
+AWB is already fixed to a specific setting.<wbr/></p>
+<p>Some LEGACY devices may not support ON; the value is then overridden to OFF.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.awbMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled.<wbr/></p>
+<p>The application-selected color transform matrix
+(<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>) and gains
+(<a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a>) are used by the camera
+device for manual white balance control.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is active.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">INCANDESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses incandescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant A.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FLUORESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses fluorescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant F2.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">WARM_FLUORESCENT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses warm fluorescent light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant F4.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DAYLIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses daylight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>While the exact white balance transforms are up to the
+camera device,<wbr/> they will approximately match the CIE
+standard illuminant D65.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CLOUDY_DAYLIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses cloudy daylight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TWILIGHT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses twilight light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SHADE</span>
+                    <span class="entry_type_enum_notes"><p>The camera device's auto-white balance routine is disabled;
+the camera device uses shade light as the assumed scene
+illumination for white balance.<wbr/></p>
+<p>The application's values for <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>
+and <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> are ignored.<wbr/>
+For devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability,<wbr/> the
+values used by the camera device for the transform and gains
+will be available in the capture result for this request.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether auto-white balance (AWB) is currently setting the color
+transform fields,<wbr/> and what its illumination target
+is.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.awbAvailableModes">android.<wbr/>control.<wbr/>awb<wbr/>Available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective if <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is AUTO.<wbr/></p>
+<p>When set to the ON mode,<wbr/> the camera device's auto-white balance
+routine is enabled,<wbr/> overriding the application's selected
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/> <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a>.<wbr/> Note that when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>
+is OFF,<wbr/> the behavior of AWB is device dependent.<wbr/> It is recommened to
+also set AWB mode to OFF or lock AWB by using <a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> before
+setting AE mode to OFF.<wbr/></p>
+<p>When set to the OFF mode,<wbr/> the camera device's auto-white balance
+routine is disabled.<wbr/> The application manually controls the white
+balance by <a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/> <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a>
+and <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a>.<wbr/></p>
+<p>When set to any other modes,<wbr/> the camera device's auto-white
+balance routine is disabled.<wbr/> The camera device uses each
+particular illumination target for white balance
+adjustment.<wbr/> The application's values for
+<a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a>,<wbr/>
+<a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> and
+<a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> are ignored.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.awbRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>awb<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5 x area_count
+                </span>
+              <span class="entry_type_visibility"> [public as meteringRectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of metering areas to use for auto-white-balance illuminant
+estimation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates within android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+              <p>Coordinates must be between <code>[(0,<wbr/>0),<wbr/> (width,<wbr/> height))</code> of
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Not available if <a href="#static_android.control.maxRegionsAwb">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Awb</a> is 0.<wbr/>
+Otherwise will always be present.<wbr/></p>
+<p>The maximum number of regions supported by the device is determined by the value
+of <a href="#static_android.control.maxRegionsAwb">android.<wbr/>control.<wbr/>max<wbr/>Regions<wbr/>Awb</a>.<wbr/></p>
+<p>The coordinate system is based on the active pixel array,<wbr/>
+with (0,<wbr/>0) being the top-left pixel in the active pixel array,<wbr/> and
+(<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>width - 1,<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>height - 1) being the
+bottom-right pixel in the active pixel array.<wbr/></p>
+<p>The weight must range from 0 to 1000,<wbr/> and represents a weight
+for every pixel in the area.<wbr/> This means that a large metering area
+with the same weight as a smaller area will have more effect in
+the metering result.<wbr/> Metering areas can partially overlap and the
+camera device will add the weights in the overlap region.<wbr/></p>
+<p>The weights are relative to weights of other white balance metering regions,<wbr/> so if
+only one region is used,<wbr/> all non-zero weights will have the same effect.<wbr/> A region with
+0 weight is ignored.<wbr/></p>
+<p>If all regions have 0 weight,<wbr/> then no specific metering area needs to be used by the
+camera device.<wbr/></p>
+<p>If the metering region is outside the used <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> returned in
+capture result metadata,<wbr/> the camera device will ignore the sections outside the crop
+region and output only the intersection rectangle as the metering region in the result
+metadata.<wbr/>  If the region is entirely outside the crop region,<wbr/> it will be ignored and
+not reported in the result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL level representation of MeteringRectangle[] is a
+int[5 * area_<wbr/>count].<wbr/>
+Every five elements represent a metering region of
+(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax,<wbr/> weight).<wbr/>
+The rectangle is defined to be inclusive on xmin and ymin,<wbr/> but
+exclusive on xmax and ymax.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.captureIntent">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>capture<wbr/>Intent
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CUSTOM</span>
+                    <span class="entry_type_enum_notes"><p>The goal of this request doesn't fall into the other
+categories.<wbr/> The camera device will default to preview-like
+behavior.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PREVIEW</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a preview-like use case.<wbr/></p>
+<p>The precapture trigger may be used to start off a metering
+w/<wbr/>flash sequence.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STILL_CAPTURE</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a still capture-type
+use case.<wbr/></p>
+<p>If the flash unit is under automatic control,<wbr/> it may fire as needed.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">VIDEO_RECORD</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a video recording
+use case.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">VIDEO_SNAPSHOT</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a video snapshot (still
+image while recording video) use case.<wbr/></p>
+<p>The camera device should take the highest-quality image
+possible (given the other settings) without disrupting the
+frame rate of video recording.<wbr/>  </p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_notes"><p>This request is for a ZSL usecase; the
+application will stream full-resolution images and
+reprocess one or several later for a final
+capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MANUAL</span>
+                    <span class="entry_type_enum_notes"><p>This request is for manual capture use case where
+the applications want to directly control the capture parameters.<wbr/></p>
+<p>For example,<wbr/> the application may wish to manually control
+<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> etc.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Information to the camera device 3A (auto-exposure,<wbr/>
+auto-focus,<wbr/> auto-white balance) routines about the purpose
+of this capture,<wbr/> to help the camera device to decide optimal 3A
+strategy.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control (except for MANUAL) is only effective if
+<code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> != OFF</code> and any 3A routine is active.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG will be supported if <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>
+contains PRIVATE_<wbr/>REPROCESSING or YUV_<wbr/>REPROCESSING.<wbr/> MANUAL will be supported if
+<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains MANUAL_<wbr/>SENSOR.<wbr/> Other intent values are
+always supported.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.awbState">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>awb<wbr/>State
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">INACTIVE</span>
+                    <span class="entry_type_enum_notes"><p>AWB is not in auto mode,<wbr/> or has not yet started metering.<wbr/></p>
+<p>When a camera device is opened,<wbr/> it starts in this
+state.<wbr/> This is a transient state,<wbr/> the camera device may
+skip reporting this state in capture
+result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SEARCHING</span>
+                    <span class="entry_type_enum_notes"><p>AWB doesn't yet have a good set of control
+values for the current scene.<wbr/></p>
+<p>This is a transient state,<wbr/> the camera device
+may skip reporting this state in capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONVERGED</span>
+                    <span class="entry_type_enum_notes"><p>AWB has a good set of control values for the
+current scene.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">LOCKED</span>
+                    <span class="entry_type_enum_notes"><p>AWB has been locked.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Current state of auto-white balance (AWB) algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Switching between or enabling AWB modes (<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>) always
+resets the AWB state to INACTIVE.<wbr/> Similarly,<wbr/> switching between <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a>,<wbr/>
+or <a href="#controls_android.control.sceneMode">android.<wbr/>control.<wbr/>scene<wbr/>Mode</a> if <code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == USE_<wbr/>SCENE_<wbr/>MODE</code> resets all
+the algorithm states to INACTIVE.<wbr/></p>
+<p>The camera device can do several state transitions between two results,<wbr/> if it is
+allowed by the state transition table.<wbr/> So INACTIVE may never actually be seen in
+a result.<wbr/></p>
+<p>The state in the result is the state for this image (in sync with this image): if
+AWB state becomes CONVERGED,<wbr/> then the image data associated with this result should
+be good to use.<wbr/></p>
+<p>Below are state transition tables for different AWB modes.<wbr/></p>
+<p>When <code><a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> != AWB_<wbr/>MODE_<wbr/>AUTO</code>:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center"></td>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device auto white balance algorithm is disabled</td>
+</tr>
+</tbody>
+</table>
+<p>When <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> is AWB_<wbr/>MODE_<wbr/>AUTO:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device initiates AWB scan</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values changing</td>
+</tr>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center"><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">SEARCHING</td>
+<td align="center">Camera device finishes AWB scan</td>
+<td align="center">CONVERGED</td>
+<td align="center">Good values,<wbr/> not changing</td>
+</tr>
+<tr>
+<td align="center">SEARCHING</td>
+<td align="center"><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">CONVERGED</td>
+<td align="center">Camera device initiates AWB scan</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values changing</td>
+</tr>
+<tr>
+<td align="center">CONVERGED</td>
+<td align="center"><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> is ON</td>
+<td align="center">LOCKED</td>
+<td align="center">Values locked</td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center"><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> is OFF</td>
+<td align="center">SEARCHING</td>
+<td align="center">Values not good after unlock</td>
+</tr>
+</tbody>
+</table>
+<p>For the above table,<wbr/> the camera device may skip reporting any state changes that happen
+without application intervention (i.<wbr/>e.<wbr/> mode switch,<wbr/> trigger,<wbr/> locking).<wbr/> Any state that
+can be skipped in that manner is called a transient state.<wbr/></p>
+<p>For example,<wbr/> for this AWB mode (AWB_<wbr/>MODE_<wbr/>AUTO),<wbr/> in addition to the state transitions
+listed in above table,<wbr/> it is also legal for the camera device to skip one or more
+transient states between two results.<wbr/> See below table for examples:</p>
+<table>
+<thead>
+<tr>
+<th align="center">State</th>
+<th align="center">Transition Cause</th>
+<th align="center">New State</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">INACTIVE</td>
+<td align="center">Camera device finished AWB scan</td>
+<td align="center">CONVERGED</td>
+<td align="center">Values are already good,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+<tr>
+<td align="center">LOCKED</td>
+<td align="center"><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a> is OFF</td>
+<td align="center">CONVERGED</td>
+<td align="center">Values good after unlock,<wbr/> transient states are skipped by camera device.<wbr/></td>
+</tr>
+</tbody>
+</table>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.effectMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>effect<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No color effect will be applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MONO</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "monocolor" effect where the image is mapped into
+a single color.<wbr/></p>
+<p>This will typically be grayscale.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NEGATIVE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "photo-negative" effect where the image's colors
+are inverted.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SOLARIZE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "solarisation" effect (Sabattier effect) where the
+image is wholly or partially reversed in
+tone.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SEPIA</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "sepia" effect where the image is mapped into warm
+gray,<wbr/> red,<wbr/> and brown tones.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">POSTERIZE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "posterization" effect where the image uses
+discrete regions of tone rather than a continuous
+gradient of tones.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">WHITEBOARD</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "whiteboard" effect where the image is typically displayed
+as regions of white,<wbr/> with black or grey details.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BLACKBOARD</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>A "blackboard" effect where the image is typically displayed
+as regions of black,<wbr/> with white or grey details.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AQUA</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>An "aqua" effect where a blue hue is added to the image.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A special color effect to apply.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableEffects">android.<wbr/>control.<wbr/>available<wbr/>Effects</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When this mode is set,<wbr/> a color effect will be applied
+to images produced by the camera device.<wbr/> The interpretation
+and implementation of these color effects is left to the
+implementor of the camera device,<wbr/> and should not be
+depended on to be consistent (or present) across all
+devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Full application control of pipeline.<wbr/></p>
+<p>All control by the device's metering and focusing (3A)
+routines is disabled,<wbr/> and no other settings in
+android.<wbr/>control.<wbr/>* have any effect,<wbr/> except that
+<a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> may be used by the camera
+device to select post-processing values for processing
+blocks that do not allow for manual control,<wbr/> or are not
+exposed by the camera API.<wbr/></p>
+<p>However,<wbr/> the camera device's 3A routines may continue to
+collect statistics and update their internal state so that
+when control is switched to AUTO mode,<wbr/> good control values
+can be immediately applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">AUTO</span>
+                    <span class="entry_type_enum_notes"><p>Use settings for each individual 3A routine.<wbr/></p>
+<p>Manual control of capture parameters is disabled.<wbr/> All
+controls in android.<wbr/>control.<wbr/>* besides sceneMode take
+effect.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">USE_SCENE_MODE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Use a specific scene mode.<wbr/></p>
+<p>Enabling this disables control.<wbr/>aeMode,<wbr/> control.<wbr/>awbMode and
+control.<wbr/>afMode controls; the camera device will ignore
+those settings while USE_<wbr/>SCENE_<wbr/>MODE is active (except for
+FACE_<wbr/>PRIORITY scene mode).<wbr/> Other control entries are still active.<wbr/>
+This setting can only be used if scene mode is supported (i.<wbr/>e.<wbr/>
+<a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a>
+contain some modes other than DISABLED).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">OFF_KEEP_STATE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Same as OFF mode,<wbr/> except that this capture will not be
+used by camera device background auto-exposure,<wbr/> auto-white balance and
+auto-focus algorithms (3A) to update their statistics.<wbr/></p>
+<p>Specifically,<wbr/> the 3A routines are locked to the last
+values set from a request with AUTO,<wbr/> OFF,<wbr/> or
+USE_<wbr/>SCENE_<wbr/>MODE,<wbr/> and any statistics or state updates
+collected from manual captures with OFF_<wbr/>KEEP_<wbr/>STATE will be
+discarded by the camera device.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Overall mode of 3A (auto-exposure,<wbr/> auto-white-balance,<wbr/> auto-focus) control
+routines.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableModes">android.<wbr/>control.<wbr/>available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is a top-level 3A control switch.<wbr/> When set to OFF,<wbr/> all 3A control
+by the camera device is disabled.<wbr/> The application must set the fields for
+capture parameters itself.<wbr/></p>
+<p>When set to AUTO,<wbr/> the individual algorithm controls in
+android.<wbr/>control.<wbr/>* are in effect,<wbr/> such as <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>.<wbr/></p>
+<p>When set to USE_<wbr/>SCENE_<wbr/>MODE,<wbr/> the individual controls in
+android.<wbr/>control.<wbr/>* are mostly disabled,<wbr/> and the camera device implements
+one of the scene mode settings (such as ACTION,<wbr/> SUNSET,<wbr/> or PARTY)
+as it wishes.<wbr/> The camera device scene mode 3A settings are provided by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html">capture results</a>.<wbr/></p>
+<p>When set to OFF_<wbr/>KEEP_<wbr/>STATE,<wbr/> it is similar to OFF mode,<wbr/> the only difference
+is that this frame will not be used by camera device background 3A statistics
+update,<wbr/> as if this frame is never captured.<wbr/> This mode can be used in the scenario
+where the application doesn't want a 3A manual control capture to affect
+the subsequent auto 3A capture results.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.sceneMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>control.<wbr/>scene<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">DISABLED</span>
+                    <span class="entry_type_enum_value">0</span>
+                    <span class="entry_type_enum_notes"><p>Indicates that no scene modes are set for a given capture request.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FACE_PRIORITY</span>
+                    <span class="entry_type_enum_notes"><p>If face detection support exists,<wbr/> use face
+detection data for auto-focus,<wbr/> auto-white balance,<wbr/> and
+auto-exposure routines.<wbr/></p>
+<p>If face detection statistics are disabled
+(i.<wbr/>e.<wbr/> <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> is set to OFF),<wbr/>
+this should still operate correctly (but will not return
+face detection statistics to the framework).<wbr/></p>
+<p>Unlike the other scene modes,<wbr/> <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+remain active when FACE_<wbr/>PRIORITY is set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ACTION</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of quickly moving objects.<wbr/></p>
+<p>Similar to SPORTS.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PORTRAIT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for still photos of people.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">LANDSCAPE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of distant macroscopic objects.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for low-light settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">NIGHT_PORTRAIT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for still photos of people in low-light
+settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">THEATRE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim,<wbr/> indoor settings where flash must
+remain off.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BEACH</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for bright,<wbr/> outdoor beach settings.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SNOW</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for bright,<wbr/> outdoor settings containing snow.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SUNSET</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for scenes of the setting sun.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STEADYPHOTO</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized to avoid blurry photos due to small amounts of
+device motion (for example: due to hand shake).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FIREWORKS</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for nighttime photos of fireworks.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SPORTS</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for photos of quickly moving people.<wbr/></p>
+<p>Similar to ACTION.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PARTY</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim,<wbr/> indoor settings with multiple moving
+people.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CANDLELIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for dim settings where the main light source
+is a flame.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BARCODE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optimized for accurately capturing a photo of barcode
+for use by camera applications that wish to read the
+barcode value.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_SPEED_VIDEO</span>
+                    <span class="entry_type_enum_deprecated">[deprecated]</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>This is deprecated,<wbr/> please use <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>
+and <a href="https://developer.android.com/reference/android/hardware/camera2/CameraConstrainedHighSpeedCaptureSession.html#createHighSpeedRequestList">CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList</a>
+for high speed video recording.<wbr/></p>
+<p>Optimized for high speed video recording (frame rate &gt;=60fps) use case.<wbr/></p>
+<p>The supported high speed video sizes and fps ranges are specified in
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/> To get desired
+output frame rates,<wbr/> the application is only allowed to select video size
+and fps range combinations listed in this static metadata.<wbr/> The fps range
+can be control via <a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a>.<wbr/></p>
+<p>In this mode,<wbr/> the camera device will override aeMode,<wbr/> awbMode,<wbr/> and afMode to
+ON,<wbr/> ON,<wbr/> and CONTINUOUS_<wbr/>VIDEO,<wbr/> respectively.<wbr/> All post-processing block mode
+controls will be overridden to be FAST.<wbr/> Therefore,<wbr/> no manual control of capture
+and post-processing parameters is possible.<wbr/> All other controls operate the
+same as when <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == AUTO.<wbr/> This means that all other
+android.<wbr/>control.<wbr/>* fields continue to work,<wbr/> such as</p>
+<ul>
+<li><a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a></li>
+<li><a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a></li>
+<li><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.effectMode">android.<wbr/>control.<wbr/>effect<wbr/>Mode</a></li>
+<li><a href="#controls_android.control.aeRegions">android.<wbr/>control.<wbr/>ae<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afRegions">android.<wbr/>control.<wbr/>af<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.awbRegions">android.<wbr/>control.<wbr/>awb<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a></li>
+<li><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a></li>
+</ul>
+<p>Outside of android.<wbr/>control.<wbr/>*,<wbr/> the following controls will work:</p>
+<ul>
+<li><a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> (automatic flash for still capture will not work since aeMode is ON)</li>
+<li><a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a> (if it is supported)</li>
+<li><a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a></li>
+<li><a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a></li>
+</ul>
+<p>For high speed recording use case,<wbr/> the actual maximum supported frame rate may
+be lower than what camera can output,<wbr/> depending on the destination Surfaces for
+the image data.<wbr/> For example,<wbr/> if the destination surface is from video encoder,<wbr/>
+the application need check if the video encoder is capable of supporting the
+high frame rate for a given video size,<wbr/> or it will end up with lower recording
+frame rate.<wbr/> If the destination surface is from preview window,<wbr/> the preview frame
+rate will be bounded by the screen refresh rate.<wbr/></p>
+<p>The camera device will only support up to 2 output high speed streams
+(processed non-stalling format defined in <a href="#static_android.request.maxNumOutputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Streams</a>)
+in this mode.<wbr/> This control will be effective only if all of below conditions are true:</p>
+<ul>
+<li>The application created no more than maxNumHighSpeedStreams processed non-stalling
+format output streams,<wbr/> where maxNumHighSpeedStreams is calculated as
+min(2,<wbr/> <a href="#static_android.request.maxNumOutputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Streams</a>[Processed (but not-stalling)]).<wbr/></li>
+<li>The stream sizes are selected from the sizes reported by
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/></li>
+<li>No processed non-stalling or raw streams are configured.<wbr/></li>
+</ul>
+<p>When above conditions are NOT satistied,<wbr/> the controls of this mode and
+<a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a> will be ignored by the camera device,<wbr/>
+the camera device will fall back to <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> <code>==</code> AUTO,<wbr/>
+and the returned capture result metadata will give the fps range choosen
+by the camera device.<wbr/></p>
+<p>Switching into or out of this mode may trigger some camera ISP/<wbr/>sensor
+reconfigurations,<wbr/> which may introduce extra latency.<wbr/> It is recommended that
+the application avoids unnecessary scene mode switch as much as possible.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HDR</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Turn on a device-specific high dynamic range (HDR) mode.<wbr/></p>
+<p>In this scene mode,<wbr/> the camera device captures images
+that keep a larger range of scene illumination levels
+visible in the final image.<wbr/> For example,<wbr/> when taking a
+picture of a object in front of a bright window,<wbr/> both
+the object and the scene through the window may be
+visible when using HDR mode,<wbr/> while in normal AUTO mode,<wbr/>
+one or the other may be poorly exposed.<wbr/> As a tradeoff,<wbr/>
+HDR mode generally takes much longer to capture a single
+image,<wbr/> has no user control,<wbr/> and may have other artifacts
+depending on the HDR method used.<wbr/></p>
+<p>Therefore,<wbr/> HDR captures operate at a much slower rate
+than regular captures.<wbr/></p>
+<p>In this mode,<wbr/> on LIMITED or FULL devices,<wbr/> when a request
+is made with a <a href="#controls_android.control.captureIntent">android.<wbr/>control.<wbr/>capture<wbr/>Intent</a> of
+STILL_<wbr/>CAPTURE,<wbr/> the camera device will capture an image
+using a high dynamic range capture technique.<wbr/>  On LEGACY
+devices,<wbr/> captures that target a JPEG-format output will
+be captured with HDR,<wbr/> and the capture intent is not
+relevant.<wbr/></p>
+<p>The HDR capture may involve the device capturing a burst
+of images internally and combining them into one,<wbr/> or it
+may involve the device using specialized high dynamic
+range capture hardware.<wbr/> In all cases,<wbr/> a single image is
+produced in response to a capture request submitted
+while in HDR mode.<wbr/></p>
+<p>Since substantial post-processing is generally needed to
+produce an HDR image,<wbr/> only YUV,<wbr/> PRIVATE,<wbr/> and JPEG
+outputs are supported for LIMITED/<wbr/>FULL device HDR
+captures,<wbr/> and only JPEG outputs are supported for LEGACY
+HDR captures.<wbr/> Using a RAW output for HDR capture is not
+supported.<wbr/></p>
+<p>Some devices may also support always-on HDR,<wbr/> which
+applies HDR processing at full frame rate.<wbr/>  For these
+devices,<wbr/> intents other than STILL_<wbr/>CAPTURE will also
+produce an HDR output with no frame rate impact compared
+to normal operation,<wbr/> though the quality may be lower
+than for STILL_<wbr/>CAPTURE intents.<wbr/></p>
+<p>If SCENE_<wbr/>MODE_<wbr/>HDR is used with unsupported output types
+or capture intents,<wbr/> the images captured will be as if
+the SCENE_<wbr/>MODE was not enabled at all.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FACE_PRIORITY_LOW_LIGHT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_notes"><p>Same as FACE_<wbr/>PRIORITY scene mode,<wbr/> except that the camera
+device will choose higher sensitivity values (<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>)
+under low light conditions.<wbr/></p>
+<p>The camera device may be tuned to expose the images in a reduced
+sensitivity range to produce the best quality images.<wbr/> For example,<wbr/>
+if the <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a> gives range of [100,<wbr/> 1600],<wbr/>
+the camera device auto-exposure routine tuning process may limit the actual
+exposure sensitivity range to [100,<wbr/> 1200] to ensure that the noise level isn't
+exessive in order to preserve the image quality.<wbr/> Under this situation,<wbr/> the image under
+low light may be under-exposed when the sensor max exposure time (bounded by the
+<a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a> when <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is one of the
+ON_<wbr/>* modes) and effective max sensitivity are reached.<wbr/> This scene mode allows the
+camera device auto-exposure routine to increase the sensitivity up to the max
+sensitivity specified by <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a> when the scene is too
+dark and the max exposure time is reached.<wbr/> The captured images may be noisier
+compared with the images captured in normal FACE_<wbr/>PRIORITY mode; therefore,<wbr/> it is
+recommended that the application only use this scene mode when it is capable of
+reducing the noise level of the captured images.<wbr/></p>
+<p>Unlike the other scene modes,<wbr/> <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+remain active when FACE_<wbr/>PRIORITY_<wbr/>LOW_<wbr/>LIGHT is set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_START</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">100</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEVICE_CUSTOM_END</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_hidden">[hidden]</span>
+                    <span class="entry_type_enum_value">127</span>
+                    <span class="entry_type_enum_notes"><p>Scene mode values within the range of
+<code>[DEVICE_<wbr/>CUSTOM_<wbr/>START,<wbr/> DEVICE_<wbr/>CUSTOM_<wbr/>END]</code> are reserved for device specific
+customized scene modes.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Control for which scene mode is currently active.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Scene modes are custom camera modes optimized for a certain set of conditions and
+capture settings.<wbr/></p>
+<p>This is the mode that that is active when
+<code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == USE_<wbr/>SCENE_<wbr/>MODE</code>.<wbr/> Aside from FACE_<wbr/>PRIORITY,<wbr/> these modes will
+disable <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>
+while in use.<wbr/></p>
+<p>The interpretation and implementation of these scene modes is left
+to the implementor of the camera device.<wbr/> Their behavior will not be
+consistent across all devices,<wbr/> and any given device may only implement
+a subset of these modes.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL implementations that include scene modes are expected to provide
+the per-scene settings to use for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/>
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>,<wbr/> and <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> in
+<a href="#static_android.control.sceneModeOverrides">android.<wbr/>control.<wbr/>scene<wbr/>Mode<wbr/>Overrides</a>.<wbr/></p>
+<p>For HIGH_<wbr/>SPEED_<wbr/>VIDEO mode,<wbr/> if it is included in <a href="#static_android.control.availableSceneModes">android.<wbr/>control.<wbr/>available<wbr/>Scene<wbr/>Modes</a>,<wbr/>
+the HAL must list supported video size and fps range in
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a>.<wbr/> For a given size,<wbr/> e.<wbr/>g.<wbr/>
+1280x720,<wbr/> if the HAL has two different sensor configurations for normal streaming
+mode and high speed streaming,<wbr/> when this scene mode is set/<wbr/>reset in a sequence of capture
+requests,<wbr/> the HAL may have to switch between different sensor modes.<wbr/>
+This mode is deprecated in HAL3.<wbr/>3,<wbr/> to support high speed video recording,<wbr/> please implement
+<a href="#static_android.control.availableHighSpeedVideoConfigurations">android.<wbr/>control.<wbr/>available<wbr/>High<wbr/>Speed<wbr/>Video<wbr/>Configurations</a> and CONSTRAINED_<wbr/>HIGH_<wbr/>SPEED_<wbr/>VIDEO
+capbility defined in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.videoStabilizationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Video stabilization is disabled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Video stabilization is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether video stabilization is
+active.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Video stabilization automatically warps images from
+the camera in order to stabilize motion between consecutive frames.<wbr/></p>
+<p>If enabled,<wbr/> video stabilization can modify the
+<a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a> to keep the video stream stabilized.<wbr/></p>
+<p>Switching between different video stabilization modes may take several
+frames to initialize,<wbr/> the camera device will report the current mode
+in capture result metadata.<wbr/> For example,<wbr/> When "ON" mode is requested,<wbr/>
+the video stabilization modes in the first several capture results may
+still be "OFF",<wbr/> and it will become "ON" when the initialization is
+done.<wbr/></p>
+<p>In addition,<wbr/> not all recording sizes or frame rates may be supported for
+stabilization by a device that reports stabilization support.<wbr/> It is guaranteed
+that an output targeting a MediaRecorder or MediaCodec will be stabilized if
+the recording resolution is less than or equal to 1920 x 1080 (width less than
+or equal to 1920,<wbr/> height less than or equal to 1080),<wbr/> and the recording
+frame rate is less than or equal to 30fps.<wbr/>  At other sizes,<wbr/> the CaptureResult
+<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a> field will return
+OFF if the recording output is not stabilized,<wbr/> or if there are no output
+Surface types that can be stabilized.<wbr/></p>
+<p>If a camera device supports both this mode and OIS
+(<a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> turning both modes on may
+produce undesirable interaction,<wbr/> so it is recommended not to enable
+both at the same time.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.control.postRawSensitivityBoost">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of additional sensitivity boost applied to output images
+after RAW sensor data is captured.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units,<wbr/> the same as android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.control.postRawSensitivityBoostRange">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Some camera devices support additional digital sensitivity boosting in the
+camera processing pipeline after sensor RAW image is captured.<wbr/>
+Such a boost will be applied to YUV/<wbr/>JPEG format output images but will not
+have effect on RAW output formats like RAW_<wbr/>SENSOR,<wbr/> RAW10,<wbr/> RAW12 or RAW_<wbr/>OPAQUE.<wbr/></p>
+<p>This key will be <code>null</code> for devices that do not support any RAW format
+outputs.<wbr/> For devices that do support RAW format outputs,<wbr/> this key will always
+present,<wbr/> and if a device does not support post RAW sensitivity boost,<wbr/> it will
+list <code>100</code> in this key.<wbr/></p>
+<p>If the camera device cannot apply the exact boost requested,<wbr/> it will reduce the
+boost to the nearest supported value.<wbr/>
+The final boost value used will be available in the output capture result.<wbr/></p>
+<p>For devices that support post RAW sensitivity boost,<wbr/> the YUV/<wbr/>JPEG output images
+of such device will have the total sensitivity of
+<code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> * <a href="#controls_android.control.postRawSensitivityBoost">android.<wbr/>control.<wbr/>post<wbr/>Raw<wbr/>Sensitivity<wbr/>Boost</a> /<wbr/> 100</code>
+The sensitivity of RAW format images will always be <code><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></code></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_demosaic" class="section">demosaic</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.demosaic.mode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>demosaic.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Minimal or no slowdown of frame rate compared to
+Bayer RAW output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Improved processing quality but the frame rate might be slowed down
+relative to raw output.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Controls the quality of the demosaicing
+processing.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_edge" class="section">edge</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.edge.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>edge.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No edge enhancement is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Apply edge enhancement at a quality level that does not slow down frame rate
+relative to sensor output.<wbr/> It may be the same as OFF if edge enhancement will
+slow down frame rate relative to sensor.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Apply high-quality edge enhancement,<wbr/> at a cost of possibly reduced output frame rate.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Edge enhancement is applied at different levels for different output streams,<wbr/>
+based on resolution.<wbr/> Streams at maximum recording resolution (see <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">CameraDevice#createCaptureSession</a>) or below have
+edge enhancement applied,<wbr/> while higher-resolution streams have no edge enhancement
+applied.<wbr/> The level of edge enhancement for low-resolution streams is tuned so that
+frame rate is not impacted,<wbr/> and the quality is equal to or better than FAST (since it
+is only applied to lower-resolution outputs,<wbr/> quality may improve from FAST).<wbr/></p>
+<p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
+with YUV or PRIVATE reprocessing,<wbr/> where the application continuously captures
+high-resolution intermediate buffers into a circular buffer,<wbr/> from which a final image is
+produced via reprocessing when a user takes a picture.<wbr/>  For such a use case,<wbr/> the
+high-resolution buffers must not have edge enhancement applied to maximize efficiency of
+preview and to avoid double-applying enhancement when reprocessed,<wbr/> while low-resolution
+buffers (used for recording or preview,<wbr/> generally) need edge enhancement applied for
+reasonable preview quality.<wbr/></p>
+<p>This mode is guaranteed to be supported by devices that support either the
+YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING capabilities
+(<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> lists either of those capabilities) and it will
+be the default mode for CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operation mode for edge
+enhancement.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.edge.availableEdgeModes">android.<wbr/>edge.<wbr/>available<wbr/>Edge<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Edge enhancement improves sharpness and details in the captured image.<wbr/> OFF means
+no enhancement will be applied by the camera device.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean camera device determined enhancement
+will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the
+camera device will use the highest-quality enhancement algorithms,<wbr/>
+even if it slows down capture rate.<wbr/> FAST means the camera device will
+not slow down capture rate when applying edge enhancement.<wbr/> FAST may be the same as OFF if
+edge enhancement will slow down capture rate.<wbr/> Every output stream will have a similar
+amount of enhancement applied.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG is meant to be used by applications that maintain a continuous circular
+buffer of high-resolution images during preview and reprocess image(s) from that buffer
+into a final capture when triggered by the user.<wbr/> In this mode,<wbr/> the camera device applies
+edge enhancement to low-resolution streams (below maximum recording resolution) to
+maximize preview quality,<wbr/> but does not apply edge enhancement to high-resolution streams,<wbr/>
+since those will be reprocessed later if necessary.<wbr/></p>
+<p>For YUV_<wbr/>REPROCESSING,<wbr/> these FAST/<wbr/>HIGH_<wbr/>QUALITY modes both mean that the camera
+device will apply FAST/<wbr/>HIGH_<wbr/>QUALITY YUV-domain edge enhancement,<wbr/> respectively.<wbr/>
+The camera device may adjust its internal edge enhancement parameters for best
+image quality based on the <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a>,<wbr/> if it is set.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For YUV_<wbr/>REPROCESSING The HAL can use <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> to
+adjust the internal edge enhancement reduction parameters appropriately to get the best
+quality images.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.edge.strength">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>edge.<wbr/>strength
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Control the amount of edge enhancement
+applied to the images</p>
+            </td>
+
+            <td class="entry_units">
+              1-10; 10 is maximum sharpening
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.edge.availableEdgeModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>edge.<wbr/>available<wbr/>Edge<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of edge enhancement modes for <a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Full-capability camera devices must always support OFF; camera devices that support
+YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING will list ZERO_<wbr/>SHUTTER_<wbr/>LAG; all devices will
+list FAST.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if edge enhancement control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.edge.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>edge.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No edge enhancement is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Apply edge enhancement at a quality level that does not slow down frame rate
+relative to sensor output.<wbr/> It may be the same as OFF if edge enhancement will
+slow down frame rate relative to sensor.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Apply high-quality edge enhancement,<wbr/> at a cost of possibly reduced output frame rate.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Edge enhancement is applied at different levels for different output streams,<wbr/>
+based on resolution.<wbr/> Streams at maximum recording resolution (see <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">CameraDevice#createCaptureSession</a>) or below have
+edge enhancement applied,<wbr/> while higher-resolution streams have no edge enhancement
+applied.<wbr/> The level of edge enhancement for low-resolution streams is tuned so that
+frame rate is not impacted,<wbr/> and the quality is equal to or better than FAST (since it
+is only applied to lower-resolution outputs,<wbr/> quality may improve from FAST).<wbr/></p>
+<p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
+with YUV or PRIVATE reprocessing,<wbr/> where the application continuously captures
+high-resolution intermediate buffers into a circular buffer,<wbr/> from which a final image is
+produced via reprocessing when a user takes a picture.<wbr/>  For such a use case,<wbr/> the
+high-resolution buffers must not have edge enhancement applied to maximize efficiency of
+preview and to avoid double-applying enhancement when reprocessed,<wbr/> while low-resolution
+buffers (used for recording or preview,<wbr/> generally) need edge enhancement applied for
+reasonable preview quality.<wbr/></p>
+<p>This mode is guaranteed to be supported by devices that support either the
+YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING capabilities
+(<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> lists either of those capabilities) and it will
+be the default mode for CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operation mode for edge
+enhancement.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.edge.availableEdgeModes">android.<wbr/>edge.<wbr/>available<wbr/>Edge<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Edge enhancement improves sharpness and details in the captured image.<wbr/> OFF means
+no enhancement will be applied by the camera device.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean camera device determined enhancement
+will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the
+camera device will use the highest-quality enhancement algorithms,<wbr/>
+even if it slows down capture rate.<wbr/> FAST means the camera device will
+not slow down capture rate when applying edge enhancement.<wbr/> FAST may be the same as OFF if
+edge enhancement will slow down capture rate.<wbr/> Every output stream will have a similar
+amount of enhancement applied.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG is meant to be used by applications that maintain a continuous circular
+buffer of high-resolution images during preview and reprocess image(s) from that buffer
+into a final capture when triggered by the user.<wbr/> In this mode,<wbr/> the camera device applies
+edge enhancement to low-resolution streams (below maximum recording resolution) to
+maximize preview quality,<wbr/> but does not apply edge enhancement to high-resolution streams,<wbr/>
+since those will be reprocessed later if necessary.<wbr/></p>
+<p>For YUV_<wbr/>REPROCESSING,<wbr/> these FAST/<wbr/>HIGH_<wbr/>QUALITY modes both mean that the camera
+device will apply FAST/<wbr/>HIGH_<wbr/>QUALITY YUV-domain edge enhancement,<wbr/> respectively.<wbr/>
+The camera device may adjust its internal edge enhancement parameters for best
+image quality based on the <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a>,<wbr/> if it is set.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For YUV_<wbr/>REPROCESSING The HAL can use <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> to
+adjust the internal edge enhancement reduction parameters appropriately to get the best
+quality images.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_flash" class="section">flash</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.flash.firingPower">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>firing<wbr/>Power
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Power for flash firing/<wbr/>torch</p>
+            </td>
+
+            <td class="entry_units">
+              10 is max power; 0 is no flash.<wbr/> Linear
+            </td>
+
+            <td class="entry_range">
+              <p>0 - 10</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Power for snapshot may use a different scale than
+for torch mode.<wbr/> Only one entry for torch mode will be
+used</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.flash.firingTime">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>firing<wbr/>Time
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Firing time of flash relative to start of
+exposure</p>
+            </td>
+
+            <td class="entry_units">
+              nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>0-(exposure time-flash duration)</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Clamped to (0,<wbr/> exposure time - flash
+duration).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.flash.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not fire the flash for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SINGLE</span>
+                    <span class="entry_type_enum_notes"><p>If the flash is available and charged,<wbr/> fire flash
+for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TORCH</span>
+                    <span class="entry_type_enum_notes"><p>Transition flash to continuously on.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired mode for for the camera device's flash control.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective when flash unit is available
+(<code><a href="#static_android.flash.info.available">android.<wbr/>flash.<wbr/>info.<wbr/>available</a> == true</code>).<wbr/></p>
+<p>When this control is used,<wbr/> the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> must be set to ON or OFF.<wbr/>
+Otherwise,<wbr/> the camera device auto-exposure related flash control (ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/>
+ON_<wbr/>ALWAYS_<wbr/>FLASH,<wbr/> or ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE) will override this control.<wbr/></p>
+<p>When set to OFF,<wbr/> the camera device will not fire flash for this capture.<wbr/></p>
+<p>When set to SINGLE,<wbr/> the camera device will fire flash regardless of the camera
+device's auto-exposure routine's result.<wbr/> When used in still capture case,<wbr/> this
+control should be used along with auto-exposure (AE) precapture metering sequence
+(<a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>),<wbr/> otherwise,<wbr/> the image may be incorrectly exposed.<wbr/></p>
+<p>When set to TORCH,<wbr/> the flash will be on continuously.<wbr/> This mode can be used
+for use cases such as preview,<wbr/> auto-focus assist,<wbr/> still capture,<wbr/> or video recording.<wbr/></p>
+<p>The flash status will be reported by <a href="#dynamic_android.flash.state">android.<wbr/>flash.<wbr/>state</a> in the capture result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+                
+            
+
+                
+          <tr class="entry" id="static_android.flash.info.available">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>info.<wbr/>available
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether this camera device has a
+flash unit.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Will be <code>false</code> if no flash is available.<wbr/></p>
+<p>If there is no flash unit,<wbr/> none of the flash controls do
+anything.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.flash.info.chargeDuration">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>info.<wbr/>charge<wbr/>Duration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Time taken before flash can fire
+again</p>
+            </td>
+
+            <td class="entry_units">
+              nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>0-1e9</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>1 second too long/<wbr/>too short for recharge? Should
+this be power-dependent?</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+        
+
+                
+          <tr class="entry" id="static_android.flash.colorTemperature">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>flash.<wbr/>color<wbr/>Temperature
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The x,<wbr/>y whitepoint of the
+flash</p>
+            </td>
+
+            <td class="entry_units">
+              pair of floats
+            </td>
+
+            <td class="entry_range">
+              <p>0-1 for both</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.flash.maxEnergy">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>flash.<wbr/>max<wbr/>Energy
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Max energy output of the flash for a full
+power single flash</p>
+            </td>
+
+            <td class="entry_units">
+              lumen-seconds
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.flash.firingPower">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>firing<wbr/>Power
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Power for flash firing/<wbr/>torch</p>
+            </td>
+
+            <td class="entry_units">
+              10 is max power; 0 is no flash.<wbr/> Linear
+            </td>
+
+            <td class="entry_range">
+              <p>0 - 10</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Power for snapshot may use a different scale than
+for torch mode.<wbr/> Only one entry for torch mode will be
+used</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.flash.firingTime">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>firing<wbr/>Time
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Firing time of flash relative to start of
+exposure</p>
+            </td>
+
+            <td class="entry_units">
+              nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>0-(exposure time-flash duration)</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Clamped to (0,<wbr/> exposure time - flash
+duration).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.flash.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not fire the flash for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SINGLE</span>
+                    <span class="entry_type_enum_notes"><p>If the flash is available and charged,<wbr/> fire flash
+for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TORCH</span>
+                    <span class="entry_type_enum_notes"><p>Transition flash to continuously on.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired mode for for the camera device's flash control.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control is only effective when flash unit is available
+(<code><a href="#static_android.flash.info.available">android.<wbr/>flash.<wbr/>info.<wbr/>available</a> == true</code>).<wbr/></p>
+<p>When this control is used,<wbr/> the <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> must be set to ON or OFF.<wbr/>
+Otherwise,<wbr/> the camera device auto-exposure related flash control (ON_<wbr/>AUTO_<wbr/>FLASH,<wbr/>
+ON_<wbr/>ALWAYS_<wbr/>FLASH,<wbr/> or ON_<wbr/>AUTO_<wbr/>FLASH_<wbr/>REDEYE) will override this control.<wbr/></p>
+<p>When set to OFF,<wbr/> the camera device will not fire flash for this capture.<wbr/></p>
+<p>When set to SINGLE,<wbr/> the camera device will fire flash regardless of the camera
+device's auto-exposure routine's result.<wbr/> When used in still capture case,<wbr/> this
+control should be used along with auto-exposure (AE) precapture metering sequence
+(<a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>),<wbr/> otherwise,<wbr/> the image may be incorrectly exposed.<wbr/></p>
+<p>When set to TORCH,<wbr/> the flash will be on continuously.<wbr/> This mode can be used
+for use cases such as preview,<wbr/> auto-focus assist,<wbr/> still capture,<wbr/> or video recording.<wbr/></p>
+<p>The flash status will be reported by <a href="#dynamic_android.flash.state">android.<wbr/>flash.<wbr/>state</a> in the capture result metadata.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.flash.state">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>flash.<wbr/>state
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">UNAVAILABLE</span>
+                    <span class="entry_type_enum_notes"><p>No flash on camera.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CHARGING</span>
+                    <span class="entry_type_enum_notes"><p>Flash is charging and cannot be fired.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">READY</span>
+                    <span class="entry_type_enum_notes"><p>Flash is ready to fire.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FIRED</span>
+                    <span class="entry_type_enum_notes"><p>Flash fired for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PARTIAL</span>
+                    <span class="entry_type_enum_notes"><p>Flash partially illuminated this frame.<wbr/></p>
+<p>This is usually due to the next or previous frame having
+the flash fire,<wbr/> and the flash spilling into this capture
+due to hardware limitations.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Current state of the flash
+unit.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When the camera device doesn't have flash unit
+(i.<wbr/>e.<wbr/> <code><a href="#static_android.flash.info.available">android.<wbr/>flash.<wbr/>info.<wbr/>available</a> == false</code>),<wbr/> this state will always be UNAVAILABLE.<wbr/>
+Other states indicate the current flash status.<wbr/></p>
+<p>In certain conditions,<wbr/> this will be available on LEGACY devices:</p>
+<ul>
+<li>Flash-less cameras always return UNAVAILABLE.<wbr/></li>
+<li>Using <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>==</code> ON_<wbr/>ALWAYS_<wbr/>FLASH
+   will always return FIRED.<wbr/></li>
+<li>Using <a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> <code>==</code> TORCH
+   will always return FIRED.<wbr/></li>
+</ul>
+<p>In all other conditions the state will not be available on
+LEGACY devices (i.<wbr/>e.<wbr/> it will be <code>null</code>).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_hotPixel" class="section">hotPixel</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.hotPixel.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>hot<wbr/>Pixel.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No hot pixel correction is applied.<wbr/></p>
+<p>The frame rate must not be reduced relative to sensor raw output
+for this option.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel correction is applied,<wbr/> without reducing frame
+rate relative to sensor raw output.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality hot pixel correction is applied,<wbr/> at a cost
+of possibly reduced frame rate relative to sensor raw output.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operational mode for hot pixel correction.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.hotPixel.availableHotPixelModes">android.<wbr/>hot<wbr/>Pixel.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Hotpixel correction interpolates out,<wbr/> or otherwise removes,<wbr/> pixels
+that do not accurately measure the incoming light (i.<wbr/>e.<wbr/> pixels that
+are stuck at an arbitrary value or are oversensitive).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.hotPixel.availableHotPixelModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>hot<wbr/>Pixel.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of hot pixel correction modes for <a href="#controls_android.hotPixel.mode">android.<wbr/>hot<wbr/>Pixel.<wbr/>mode</a> that are supported by this
+camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.hotPixel.mode">android.<wbr/>hot<wbr/>Pixel.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>FULL mode camera devices will always support FAST.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>To avoid performance issues,<wbr/> there will be significantly fewer hot
+pixels than actual pixels on the camera sensor.<wbr/>
+HAL must support both FAST and HIGH_<wbr/>QUALITY if hot pixel correction control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.hotPixel.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>hot<wbr/>Pixel.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No hot pixel correction is applied.<wbr/></p>
+<p>The frame rate must not be reduced relative to sensor raw output
+for this option.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel correction is applied,<wbr/> without reducing frame
+rate relative to sensor raw output.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality hot pixel correction is applied,<wbr/> at a cost
+of possibly reduced frame rate relative to sensor raw output.<wbr/></p>
+<p>The hotpixel map may be returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operational mode for hot pixel correction.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.hotPixel.availableHotPixelModes">android.<wbr/>hot<wbr/>Pixel.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Hotpixel correction interpolates out,<wbr/> or otherwise removes,<wbr/> pixels
+that do not accurately measure the incoming light (i.<wbr/>e.<wbr/> pixels that
+are stuck at an arbitrary value or are oversensitive).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_jpeg" class="section">jpeg</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.jpeg.gpsLocation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Location
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [java_public as location]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A location object to use when generating image GPS metadata.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Setting a location object in a request will include the GPS coordinates of the location
+into any JPEG images captured based on the request.<wbr/> These coordinates can then be
+viewed by anyone who receives the JPEG image.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.gpsCoordinates">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Coordinates
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">double</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">latitude,<wbr/> longitude,<wbr/> altitude.<wbr/> First two in degrees,<wbr/> the third in meters</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>GPS coordinates to include in output JPEG
+EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>(-180 - 180],<wbr/> [-90,<wbr/>90],<wbr/> [-inf,<wbr/> inf]</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.gpsProcessingMethod">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Processing<wbr/>Method
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [ndk_public as string]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>32 characters describing GPS algorithm to
+include in EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              UTF-8 null-terminated string
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.gpsTimestamp">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Timestamp
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Time GPS fix was made to include in
+EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              UTC in seconds since January 1,<wbr/> 1970
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.orientation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>orientation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The orientation for a JPEG image.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Degrees in multiples of 90
+            </td>
+
+            <td class="entry_range">
+              <p>0,<wbr/> 90,<wbr/> 180,<wbr/> 270</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The clockwise rotation angle in degrees,<wbr/> relative to the orientation
+to the camera,<wbr/> that the JPEG picture needs to be rotated by,<wbr/> to be viewed
+upright.<wbr/></p>
+<p>Camera devices may either encode this value into the JPEG EXIF header,<wbr/> or
+rotate the image data to match this orientation.<wbr/> When the image data is rotated,<wbr/>
+the thumbnail data will also be rotated.<wbr/></p>
+<p>Note that this orientation is relative to the orientation of the camera sensor,<wbr/> given
+by <a href="#static_android.sensor.orientation">android.<wbr/>sensor.<wbr/>orientation</a>.<wbr/></p>
+<p>To translate from the device orientation given by the Android sensor APIs,<wbr/> the following
+sample code may be used:</p>
+<pre><code>private int getJpegOrientation(CameraCharacteristics c,<wbr/> int deviceOrientation) {
+    if (deviceOrientation == android.<wbr/>view.<wbr/>Orientation<wbr/>Event<wbr/>Listener.<wbr/>ORIENTATION_<wbr/>UNKNOWN) return 0;
+    int sensorOrientation = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>SENSOR_<wbr/>ORIENTATION);
+
+    //<wbr/> Round device orientation to a multiple of 90
+    deviceOrientation = (deviceOrientation + 45) /<wbr/> 90 * 90;
+
+    //<wbr/> Reverse device orientation for front-facing cameras
+    boolean facingFront = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>LENS_<wbr/>FACING) == Camera<wbr/>Characteristics.<wbr/>LENS_<wbr/>FACING_<wbr/>FRONT;
+    if (facingFront) deviceOrientation = -deviceOrientation;
+
+    //<wbr/> Calculate desired JPEG orientation relative to camera orientation to make
+    //<wbr/> the image upright relative to the device orientation
+    int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;
+
+    return jpegOrientation;
+}
+</code></pre>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.quality">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>quality
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Compression quality of the final JPEG
+image.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>1-100; larger is higher quality</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>85-95 is typical usage range.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.thumbnailQuality">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>thumbnail<wbr/>Quality
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Compression quality of JPEG
+thumbnail.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>1-100; larger is higher quality</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.jpeg.thumbnailSize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>jpeg.<wbr/>thumbnail<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as size]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Resolution of embedded JPEG thumbnail.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.jpeg.availableThumbnailSizes">android.<wbr/>jpeg.<wbr/>available<wbr/>Thumbnail<wbr/>Sizes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to (0,<wbr/> 0) value,<wbr/> the JPEG EXIF will not contain thumbnail,<wbr/>
+but the captured JPEG will still be a valid image.<wbr/></p>
+<p>For best results,<wbr/> when issuing a request for a JPEG image,<wbr/> the thumbnail size selected
+should have the same aspect ratio as the main JPEG output.<wbr/></p>
+<p>If the thumbnail image aspect ratio differs from the JPEG primary image aspect
+ratio,<wbr/> the camera device creates the thumbnail by cropping it from the primary image.<wbr/>
+For example,<wbr/> if the primary image has 4:3 aspect ratio,<wbr/> the thumbnail image has
+16:9 aspect ratio,<wbr/> the primary image will be cropped vertically (letterbox) to
+generate the thumbnail image.<wbr/> The thumbnail image will always have a smaller Field
+Of View (FOV) than the primary image when aspect ratios differ.<wbr/></p>
+<p>When an <a href="#controls_android.jpeg.orientation">android.<wbr/>jpeg.<wbr/>orientation</a> of non-zero degree is requested,<wbr/>
+the camera device will handle thumbnail rotation in one of the following ways:</p>
+<ul>
+<li>Set the <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
+  and keep jpeg and thumbnail image data unrotated.<wbr/></li>
+<li>Rotate the jpeg and thumbnail image data and not set
+  <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>.<wbr/> In this
+  case,<wbr/> LIMITED or FULL hardware level devices will report rotated thumnail size in
+  capture result,<wbr/> so the width and height will be interchanged if 90 or 270 degree
+  orientation is requested.<wbr/> LEGACY device will always report unrotated thumbnail
+  size.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must not squeeze or stretch the downscaled primary image to generate thumbnail.<wbr/>
+The cropping must be done on the primary jpeg image rather than the sensor active array.<wbr/>
+The stream cropping rule specified by "S5.<wbr/> Cropping" in camera3.<wbr/>h doesn't apply to the
+thumbnail image cropping.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.jpeg.availableThumbnailSizes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>available<wbr/>Thumbnail<wbr/>Sizes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2 x n
+                </span>
+              <span class="entry_type_visibility"> [public as size]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of JPEG thumbnail sizes for <a href="#controls_android.jpeg.thumbnailSize">android.<wbr/>jpeg.<wbr/>thumbnail<wbr/>Size</a> supported by this
+camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This list will include at least one non-zero resolution,<wbr/> plus <code>(0,<wbr/>0)</code> for indicating no
+thumbnail should be generated.<wbr/></p>
+<p>Below condiditions will be satisfied for this size list:</p>
+<ul>
+<li>The sizes will be sorted by increasing pixel area (width x height).<wbr/>
+If several resolutions have the same area,<wbr/> they will be sorted by increasing width.<wbr/></li>
+<li>The aspect ratio of the largest thumbnail size will be same as the
+aspect ratio of largest JPEG output size in <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a>.<wbr/>
+The largest size is defined as the size that has the largest pixel area
+in a given size list.<wbr/></li>
+<li>Each output JPEG size in <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> will have at least
+one corresponding size that has the same aspect ratio in availableThumbnailSizes,<wbr/>
+and vice versa.<wbr/></li>
+<li>All non-<code>(0,<wbr/> 0)</code> sizes will have non-zero widths and heights.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.jpeg.maxSize">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>max<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum size in bytes for the compressed
+JPEG buffer</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Must be large enough to fit any JPEG produced by
+the camera</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is used for sizing the gralloc buffers for
+JPEG</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.jpeg.gpsLocation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Location
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [java_public as location]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A location object to use when generating image GPS metadata.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Setting a location object in a request will include the GPS coordinates of the location
+into any JPEG images captured based on the request.<wbr/> These coordinates can then be
+viewed by anyone who receives the JPEG image.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.gpsCoordinates">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Coordinates
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">double</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">latitude,<wbr/> longitude,<wbr/> altitude.<wbr/> First two in degrees,<wbr/> the third in meters</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>GPS coordinates to include in output JPEG
+EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>(-180 - 180],<wbr/> [-90,<wbr/>90],<wbr/> [-inf,<wbr/> inf]</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.gpsProcessingMethod">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Processing<wbr/>Method
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [ndk_public as string]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>32 characters describing GPS algorithm to
+include in EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              UTF-8 null-terminated string
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.gpsTimestamp">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>gps<wbr/>Timestamp
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Time GPS fix was made to include in
+EXIF.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              UTC in seconds since January 1,<wbr/> 1970
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.orientation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>orientation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The orientation for a JPEG image.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Degrees in multiples of 90
+            </td>
+
+            <td class="entry_range">
+              <p>0,<wbr/> 90,<wbr/> 180,<wbr/> 270</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The clockwise rotation angle in degrees,<wbr/> relative to the orientation
+to the camera,<wbr/> that the JPEG picture needs to be rotated by,<wbr/> to be viewed
+upright.<wbr/></p>
+<p>Camera devices may either encode this value into the JPEG EXIF header,<wbr/> or
+rotate the image data to match this orientation.<wbr/> When the image data is rotated,<wbr/>
+the thumbnail data will also be rotated.<wbr/></p>
+<p>Note that this orientation is relative to the orientation of the camera sensor,<wbr/> given
+by <a href="#static_android.sensor.orientation">android.<wbr/>sensor.<wbr/>orientation</a>.<wbr/></p>
+<p>To translate from the device orientation given by the Android sensor APIs,<wbr/> the following
+sample code may be used:</p>
+<pre><code>private int getJpegOrientation(CameraCharacteristics c,<wbr/> int deviceOrientation) {
+    if (deviceOrientation == android.<wbr/>view.<wbr/>Orientation<wbr/>Event<wbr/>Listener.<wbr/>ORIENTATION_<wbr/>UNKNOWN) return 0;
+    int sensorOrientation = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>SENSOR_<wbr/>ORIENTATION);
+
+    //<wbr/> Round device orientation to a multiple of 90
+    deviceOrientation = (deviceOrientation + 45) /<wbr/> 90 * 90;
+
+    //<wbr/> Reverse device orientation for front-facing cameras
+    boolean facingFront = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>LENS_<wbr/>FACING) == Camera<wbr/>Characteristics.<wbr/>LENS_<wbr/>FACING_<wbr/>FRONT;
+    if (facingFront) deviceOrientation = -deviceOrientation;
+
+    //<wbr/> Calculate desired JPEG orientation relative to camera orientation to make
+    //<wbr/> the image upright relative to the device orientation
+    int jpegOrientation = (sensorOrientation + deviceOrientation + 360) % 360;
+
+    return jpegOrientation;
+}
+</code></pre>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.quality">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>quality
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Compression quality of the final JPEG
+image.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>1-100; larger is higher quality</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>85-95 is typical usage range.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.size">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>jpeg.<wbr/>size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The size of the compressed JPEG image,<wbr/> in
+bytes</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If no JPEG output is produced for the request,<wbr/>
+this must be 0.<wbr/></p>
+<p>Otherwise,<wbr/> this describes the real size of the compressed
+JPEG image placed in the output stream.<wbr/>  More specifically,<wbr/>
+if <a href="#static_android.jpeg.maxSize">android.<wbr/>jpeg.<wbr/>max<wbr/>Size</a> = 1000000,<wbr/> and a specific capture
+has <a href="#dynamic_android.jpeg.size">android.<wbr/>jpeg.<wbr/>size</a> = 500000,<wbr/> then the output buffer from
+the JPEG stream will be 1000000 bytes,<wbr/> of which the first
+500000 make up the real data.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.thumbnailQuality">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>jpeg.<wbr/>thumbnail<wbr/>Quality
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Compression quality of JPEG
+thumbnail.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>1-100; larger is higher quality</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.jpeg.thumbnailSize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>jpeg.<wbr/>thumbnail<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as size]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Resolution of embedded JPEG thumbnail.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.jpeg.availableThumbnailSizes">android.<wbr/>jpeg.<wbr/>available<wbr/>Thumbnail<wbr/>Sizes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to (0,<wbr/> 0) value,<wbr/> the JPEG EXIF will not contain thumbnail,<wbr/>
+but the captured JPEG will still be a valid image.<wbr/></p>
+<p>For best results,<wbr/> when issuing a request for a JPEG image,<wbr/> the thumbnail size selected
+should have the same aspect ratio as the main JPEG output.<wbr/></p>
+<p>If the thumbnail image aspect ratio differs from the JPEG primary image aspect
+ratio,<wbr/> the camera device creates the thumbnail by cropping it from the primary image.<wbr/>
+For example,<wbr/> if the primary image has 4:3 aspect ratio,<wbr/> the thumbnail image has
+16:9 aspect ratio,<wbr/> the primary image will be cropped vertically (letterbox) to
+generate the thumbnail image.<wbr/> The thumbnail image will always have a smaller Field
+Of View (FOV) than the primary image when aspect ratios differ.<wbr/></p>
+<p>When an <a href="#controls_android.jpeg.orientation">android.<wbr/>jpeg.<wbr/>orientation</a> of non-zero degree is requested,<wbr/>
+the camera device will handle thumbnail rotation in one of the following ways:</p>
+<ul>
+<li>Set the <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>
+  and keep jpeg and thumbnail image data unrotated.<wbr/></li>
+<li>Rotate the jpeg and thumbnail image data and not set
+  <a href="https://developer.android.com/reference/android/media/ExifInterface.html#TAG_ORIENTATION">EXIF orientation flag</a>.<wbr/> In this
+  case,<wbr/> LIMITED or FULL hardware level devices will report rotated thumnail size in
+  capture result,<wbr/> so the width and height will be interchanged if 90 or 270 degree
+  orientation is requested.<wbr/> LEGACY device will always report unrotated thumbnail
+  size.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must not squeeze or stretch the downscaled primary image to generate thumbnail.<wbr/>
+The cropping must be done on the primary jpeg image rather than the sensor active array.<wbr/>
+The stream cropping rule specified by "S5.<wbr/> Cropping" in camera3.<wbr/>h doesn't apply to the
+thumbnail image cropping.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_lens" class="section">lens</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.lens.aperture">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>aperture
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired lens aperture size,<wbr/> as a ratio of lens focal length to the
+effective aperture diameter.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              The f-number (f/<wbr/>N)
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableApertures">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Apertures</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Setting this value is only supported on the camera devices that have a variable
+aperture lens.<wbr/></p>
+<p>When this is supported and <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is OFF,<wbr/>
+this can be set along with <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and <a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>
+to achieve manual exposure control.<wbr/></p>
+<p>The requested aperture value may take several frames to reach the
+requested value; the camera device will report the current (intermediate)
+aperture size in capture result metadata while the aperture is changing.<wbr/>
+While the aperture is still changing,<wbr/> <a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will be set to MOVING.<wbr/></p>
+<p>When this is supported and <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is one of
+the ON modes,<wbr/> this will be overridden by the camera device
+auto-exposure algorithm,<wbr/> the overridden values are then provided
+back to the user in the corresponding result.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.lens.filterDensity">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>filter<wbr/>Density
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired setting for the lens neutral density filter(s).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Exposure Value (EV)
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableFilterDensities">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Filter<wbr/>Densities</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control will not be supported on most camera devices.<wbr/></p>
+<p>Lens filters are typically used to lower the amount of light the
+sensor is exposed to (measured in steps of EV).<wbr/> As used here,<wbr/> an EV
+step is the standard logarithmic representation,<wbr/> which are
+non-negative,<wbr/> and inversely proportional to the amount of light
+hitting the sensor.<wbr/>  For example,<wbr/> setting this to 0 would result
+in no reduction of the incoming light,<wbr/> and setting this to 2 would
+mean that the filter is set to reduce incoming light by two stops
+(allowing 1/<wbr/>4 of the prior amount of light to the sensor).<wbr/></p>
+<p>It may take several frames before the lens filter density changes
+to the requested value.<wbr/> While the filter density is still changing,<wbr/>
+<a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will be set to MOVING.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.lens.focalLength">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>focal<wbr/>Length
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired lens focal length; used for optical zoom.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Millimeters
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableFocalLengths">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Focal<wbr/>Lengths</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This setting controls the physical focal length of the camera
+device's lens.<wbr/> Changing the focal length changes the field of
+view of the camera device,<wbr/> and is usually used for optical zoom.<wbr/></p>
+<p>Like <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> and <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a>,<wbr/> this
+setting won't be applied instantaneously,<wbr/> and it may take several
+frames before the lens can change to the requested focal length.<wbr/>
+While the focal length is still changing,<wbr/> <a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will
+be set to MOVING.<wbr/></p>
+<p>Optical zoom will not be supported on most devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.lens.focusDistance">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>focus<wbr/>Distance
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Desired distance to plane of sharpest focus,<wbr/>
+measured from frontmost surface of the lens.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              See android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration for details
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control can be used for setting manual focus,<wbr/> on devices that support
+the MANUAL_<wbr/>SENSOR capability and have a variable-focus lens (see
+<a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a>).<wbr/></p>
+<p>A value of <code>0.<wbr/>0f</code> means infinity focus.<wbr/> The value set will be clamped to
+<code>[0.<wbr/>0f,<wbr/> <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a>]</code>.<wbr/></p>
+<p>Like <a href="#controls_android.lens.focalLength">android.<wbr/>lens.<wbr/>focal<wbr/>Length</a>,<wbr/> this setting won't be applied
+instantaneously,<wbr/> and it may take several frames before the lens
+can move to the requested focus distance.<wbr/> While the lens is still moving,<wbr/>
+<a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will be set to MOVING.<wbr/></p>
+<p>LEGACY devices support at most setting this to <code>0.<wbr/>0f</code>
+for infinity focus.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.lens.opticalStabilizationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Optical stabilization is unavailable.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optical stabilization is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Sets whether the camera device uses optical image stabilization (OIS)
+when capturing images.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>OIS is used to compensate for motion blur due to small
+movements of the camera during capture.<wbr/> Unlike digital image
+stabilization (<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> OIS
+makes use of mechanical elements to stabilize the camera
+sensor,<wbr/> and thus allows for longer exposure times before
+camera shake becomes apparent.<wbr/></p>
+<p>Switching between different optical stabilization modes may take several
+frames to initialize,<wbr/> the camera device will report the current mode in
+capture result metadata.<wbr/> For example,<wbr/> When "ON" mode is requested,<wbr/> the
+optical stabilization modes in the first several capture results may still
+be "OFF",<wbr/> and it will become "ON" when the initialization is done.<wbr/></p>
+<p>If a camera device supports both OIS and digital image stabilization
+(<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> turning both modes on may produce undesirable
+interaction,<wbr/> so it is recommended not to enable both at the same time.<wbr/></p>
+<p>Not all devices will support OIS; see
+<a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a> for
+available controls.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+                
+            
+
+                
+          <tr class="entry" id="static_android.lens.info.availableApertures">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Apertures
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of aperture size values for <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              The aperture f-number
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the camera device doesn't support a variable lens aperture,<wbr/>
+this list will contain only one value,<wbr/> which is the fixed aperture size.<wbr/></p>
+<p>If the camera device supports a variable aperture,<wbr/> the aperture values
+in this list will be sorted in ascending order.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.availableFilterDensities">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Filter<wbr/>Densities
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of neutral density filter values for
+<a href="#controls_android.lens.filterDensity">android.<wbr/>lens.<wbr/>filter<wbr/>Density</a> that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Exposure value (EV)
+            </td>
+
+            <td class="entry_range">
+              <p>Values are &gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If a neutral density filter is not supported by this camera device,<wbr/>
+this list will contain only 0.<wbr/> Otherwise,<wbr/> this list will include every
+filter density supported by the camera device,<wbr/> in ascending order.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.availableFocalLengths">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Focal<wbr/>Lengths
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">The list of available focal lengths</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of focal lengths for <a href="#controls_android.lens.focalLength">android.<wbr/>lens.<wbr/>focal<wbr/>Length</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Millimeters
+            </td>
+
+            <td class="entry_range">
+              <p>Values are &gt; 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If optical zoom is not supported,<wbr/> this list will only contain
+a single value corresponding to the fixed focal length of the
+device.<wbr/> Otherwise,<wbr/> this list will include every focal length supported
+by the camera device,<wbr/> in ascending order.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.availableOpticalStabilization">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of optical image stabilization (OIS) modes for
+<a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a> that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If OIS is not supported by a given camera device,<wbr/> this list will
+contain only OFF.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.hyperfocalDistance">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>hyperfocal<wbr/>Distance
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Hyperfocal distance for this lens.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              See android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration for details
+            </td>
+
+            <td class="entry_range">
+              <p>If lens is fixed focus,<wbr/> &gt;= 0.<wbr/> If lens has focuser unit,<wbr/> the value is
+within <code>(0.<wbr/>0f,<wbr/> <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a>]</code></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the lens is not fixed focus,<wbr/> the camera device will report this
+field when <a href="#static_android.lens.info.focusDistanceCalibration">android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration</a> is APPROXIMATE or CALIBRATED.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.minimumFocusDistance">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Shortest distance from frontmost surface
+of the lens that can be brought into sharp focus.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              See android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration for details
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the lens is fixed-focus,<wbr/> this will be
+0.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Mandatory for FULL devices; LIMITED devices
+must always set this value to 0 for fixed-focus; and may omit
+the minimum focus distance otherwise.<wbr/></p>
+<p>This field is also mandatory for all devices advertising
+the MANUAL_<wbr/>SENSOR capability.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.shadingMapSize">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>info.<wbr/>shading<wbr/>Map<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as size]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">width and height (N,<wbr/> M) of lens shading map provided by the camera device.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Dimensions of lens shading map.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Both values &gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The map should be on the order of 30-40 rows and columns,<wbr/> and
+must be smaller than 64x64.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.info.focusDistanceCalibration">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">UNCALIBRATED</span>
+                    <span class="entry_type_enum_notes"><p>The lens focus distance is not accurate,<wbr/> and the units used for
+<a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> do not correspond to any physical units.<wbr/></p>
+<p>Setting the lens to the same focus distance on separate occasions may
+result in a different real focus distance,<wbr/> depending on factors such
+as the orientation of the device,<wbr/> the age of the focusing mechanism,<wbr/>
+and the device temperature.<wbr/> The focus distance value will still be
+in the range of <code>[0,<wbr/> <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a>]</code>,<wbr/> where 0
+represents the farthest focus.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">APPROXIMATE</span>
+                    <span class="entry_type_enum_notes"><p>The lens focus distance is measured in diopters.<wbr/></p>
+<p>However,<wbr/> setting the lens to the same focus distance
+on separate occasions may result in a different real
+focus distance,<wbr/> depending on factors such as the
+orientation of the device,<wbr/> the age of the focusing
+mechanism,<wbr/> and the device temperature.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CALIBRATED</span>
+                    <span class="entry_type_enum_notes"><p>The lens focus distance is measured in diopters,<wbr/> and
+is calibrated.<wbr/></p>
+<p>The lens mechanism is calibrated so that setting the
+same focus distance is repeatable on multiple
+occasions with good accuracy,<wbr/> and the focus distance
+corresponds to the real physical distance to the plane
+of best focus.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The lens focus distance calibration quality.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The lens focus distance calibration quality determines the reliability of
+focus related metadata entries,<wbr/> i.<wbr/>e.<wbr/> <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a>,<wbr/>
+<a href="#dynamic_android.lens.focusRange">android.<wbr/>lens.<wbr/>focus<wbr/>Range</a>,<wbr/> <a href="#static_android.lens.info.hyperfocalDistance">android.<wbr/>lens.<wbr/>info.<wbr/>hyperfocal<wbr/>Distance</a>,<wbr/> and
+<a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a>.<wbr/></p>
+<p>APPROXIMATE and CALIBRATED devices report the focus metadata in
+units of diopters (1/<wbr/>meter),<wbr/> so <code>0.<wbr/>0f</code> represents focusing at infinity,<wbr/>
+and increasing positive numbers represent focusing closer and closer
+to the camera device.<wbr/> The focus distance control also uses diopters
+on these devices.<wbr/></p>
+<p>UNCALIBRATED devices do not use units that are directly comparable
+to any real physical measurement,<wbr/> but <code>0.<wbr/>0f</code> still represents farthest
+focus,<wbr/> and <a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> represents the
+nearest focus the device can achieve.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For devices advertise APPROXIMATE quality or higher,<wbr/> diopters 0 (infinity
+focus) must work.<wbr/> When autofocus is disabled (<a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a> == OFF)
+and the lens focus distance is set to 0 diopters
+(<a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> == 0),<wbr/> the lens will move to focus at infinity
+and is stably focused at infinity even if the device tilts.<wbr/> It may take the
+lens some time to move; during the move the lens state should be MOVING and
+the output diopter value should be changing toward 0.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+        
+
+                
+          <tr class="entry" id="static_android.lens.facing">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>lens.<wbr/>facing
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FRONT</span>
+                    <span class="entry_type_enum_notes"><p>The camera device faces the same direction as the device's screen.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BACK</span>
+                    <span class="entry_type_enum_notes"><p>The camera device faces the opposite direction as the device's screen.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">EXTERNAL</span>
+                    <span class="entry_type_enum_notes"><p>The camera device is an external camera,<wbr/> and has no fixed facing relative to the
+device's screen.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Direction the camera faces relative to
+device screen.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.poseRotation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>pose<wbr/>Rotation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The orientation of the camera relative to the sensor
+coordinate system.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Quaternion coefficients
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The four coefficients that describe the quaternion
+rotation from the Android sensor coordinate system to a
+camera-aligned coordinate system where the X-axis is
+aligned with the long side of the image sensor,<wbr/> the Y-axis
+is aligned with the short side of the image sensor,<wbr/> and
+the Z-axis is aligned with the optical axis of the sensor.<wbr/></p>
+<p>To convert from the quaternion coefficients <code>(x,<wbr/>y,<wbr/>z,<wbr/>w)</code>
+to the axis of rotation <code>(a_<wbr/>x,<wbr/> a_<wbr/>y,<wbr/> a_<wbr/>z)</code> and rotation
+amount <code>theta</code>,<wbr/> the following formulas can be used:</p>
+<pre><code> theta = 2 * acos(w)
+a_<wbr/>x = x /<wbr/> sin(theta/<wbr/>2)
+a_<wbr/>y = y /<wbr/> sin(theta/<wbr/>2)
+a_<wbr/>z = z /<wbr/> sin(theta/<wbr/>2)
+</code></pre>
+<p>To create a 3x3 rotation matrix that applies the rotation
+defined by this quaternion,<wbr/> the following matrix can be
+used:</p>
+<pre><code>R = [ 1 - 2y^2 - 2z^2,<wbr/>       2xy - 2zw,<wbr/>       2xz + 2yw,<wbr/>
+           2xy + 2zw,<wbr/> 1 - 2x^2 - 2z^2,<wbr/>       2yz - 2xw,<wbr/>
+           2xz - 2yw,<wbr/>       2yz + 2xw,<wbr/> 1 - 2x^2 - 2y^2 ]
+</code></pre>
+<p>This matrix can then be used to apply the rotation to a
+ column vector point with</p>
+<p><code>p' = Rp</code></p>
+<p>where <code>p</code> is in the device sensor coordinate system,<wbr/> and
+ <code>p'</code> is in the camera-oriented coordinate system.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.poseTranslation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>pose<wbr/>Translation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Position of the camera optical center.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Meters
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The position of the camera device's lens optical center,<wbr/>
+as a three-dimensional vector <code>(x,<wbr/>y,<wbr/>z)</code>,<wbr/> relative to the
+optical center of the largest camera device facing in the
+same direction as this camera,<wbr/> in the <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate
+axes</a>.<wbr/> Note that only the axis definitions are shared with
+the sensor coordinate system,<wbr/> but not the origin.<wbr/></p>
+<p>If this device is the largest or only camera device with a
+given facing,<wbr/> then this position will be <code>(0,<wbr/> 0,<wbr/> 0)</code>; a
+camera device with a lens optical center located 3 cm from
+the main sensor along the +X axis (to the right from the
+user's perspective) will report <code>(0.<wbr/>03,<wbr/> 0,<wbr/> 0)</code>.<wbr/></p>
+<p>To transform a pixel coordinates between two cameras
+facing the same direction,<wbr/> first the source camera
+<a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a> must be corrected for.<wbr/>  Then
+the source camera <a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a> needs
+to be applied,<wbr/> followed by the <a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a>
+of the source camera,<wbr/> the translation of the source camera
+relative to the destination camera,<wbr/> the
+<a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a> of the destination camera,<wbr/> and
+finally the inverse of <a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a>
+of the destination camera.<wbr/> This obtains a
+radial-distortion-free coordinate in the destination
+camera pixel coordinates.<wbr/></p>
+<p>To compare this against a real image from the destination
+camera,<wbr/> the destination camera image then needs to be
+corrected for radial distortion before comparison or
+sampling.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.intrinsicCalibration">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The parameters for this camera device's intrinsic
+calibration.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Pixels in the
+            android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size
+            coordinate system.<wbr/>
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The five calibration parameters that describe the
+transform from camera-centric 3D coordinates to sensor
+pixel coordinates:</p>
+<pre><code>[f_<wbr/>x,<wbr/> f_<wbr/>y,<wbr/> c_<wbr/>x,<wbr/> c_<wbr/>y,<wbr/> s]
+</code></pre>
+<p>Where <code>f_<wbr/>x</code> and <code>f_<wbr/>y</code> are the horizontal and vertical
+focal lengths,<wbr/> <code>[c_<wbr/>x,<wbr/> c_<wbr/>y]</code> is the position of the optical
+axis,<wbr/> and <code>s</code> is a skew parameter for the sensor plane not
+being aligned with the lens plane.<wbr/></p>
+<p>These are typically used within a transformation matrix K:</p>
+<pre><code>K = [ f_<wbr/>x,<wbr/>   s,<wbr/> c_<wbr/>x,<wbr/>
+       0,<wbr/> f_<wbr/>y,<wbr/> c_<wbr/>y,<wbr/>
+       0    0,<wbr/>   1 ]
+</code></pre>
+<p>which can then be combined with the camera pose rotation
+<code>R</code> and translation <code>t</code> (<a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a> and
+<a href="#static_android.lens.poseTranslation">android.<wbr/>lens.<wbr/>pose<wbr/>Translation</a>,<wbr/> respective) to calculate the
+complete transform from world coordinates to pixel
+coordinates:</p>
+<pre><code>P = [ K 0   * [ R t
+     0 1 ]     0 1 ]
+</code></pre>
+<p>and with <code>p_<wbr/>w</code> being a point in the world coordinate system
+and <code>p_<wbr/>s</code> being a point in the camera active pixel array
+coordinate system,<wbr/> and with the mapping including the
+homogeneous division by z:</p>
+<pre><code> p_<wbr/>h = (x_<wbr/>h,<wbr/> y_<wbr/>h,<wbr/> z_<wbr/>h) = P p_<wbr/>w
+p_<wbr/>s = p_<wbr/>h /<wbr/> z_<wbr/>h
+</code></pre>
+<p>so <code>[x_<wbr/>s,<wbr/> y_<wbr/>s]</code> is the pixel coordinates of the world
+point,<wbr/> <code>z_<wbr/>s = 1</code>,<wbr/> and <code>w_<wbr/>s</code> is a measurement of disparity
+(depth) in pixel coordinates.<wbr/></p>
+<p>Note that the coordinate system for this transform is the
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> system,<wbr/>
+where <code>(0,<wbr/>0)</code> is the top-left of the
+preCorrectionActiveArraySize rectangle.<wbr/> Once the pose and
+intrinsic calibration transforms have been applied to a
+world point,<wbr/> then the <a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a>
+transform needs to be applied,<wbr/> and the result adjusted to
+be in the <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> coordinate
+system (where <code>(0,<wbr/> 0)</code> is the top-left of the
+activeArraySize rectangle),<wbr/> to determine the final pixel
+coordinate of the world point for processed (non-RAW)
+output buffers.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.lens.radialDistortion">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>radial<wbr/>Distortion
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  6
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The correction coefficients to correct for this camera device's
+radial and tangential lens distortion.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Unitless coefficients.<wbr/>
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Four radial distortion coefficients <code>[kappa_<wbr/>0,<wbr/> kappa_<wbr/>1,<wbr/> kappa_<wbr/>2,<wbr/>
+kappa_<wbr/>3]</code> and two tangential distortion coefficients
+<code>[kappa_<wbr/>4,<wbr/> kappa_<wbr/>5]</code> that can be used to correct the
+lens's geometric distortion with the mapping equations:</p>
+<pre><code> x_<wbr/>c = x_<wbr/>i * ( kappa_<wbr/>0 + kappa_<wbr/>1 * r^2 + kappa_<wbr/>2 * r^4 + kappa_<wbr/>3 * r^6 ) +
+       kappa_<wbr/>4 * (2 * x_<wbr/>i * y_<wbr/>i) + kappa_<wbr/>5 * ( r^2 + 2 * x_<wbr/>i^2 )
+ y_<wbr/>c = y_<wbr/>i * ( kappa_<wbr/>0 + kappa_<wbr/>1 * r^2 + kappa_<wbr/>2 * r^4 + kappa_<wbr/>3 * r^6 ) +
+       kappa_<wbr/>5 * (2 * x_<wbr/>i * y_<wbr/>i) + kappa_<wbr/>4 * ( r^2 + 2 * y_<wbr/>i^2 )
+</code></pre>
+<p>Here,<wbr/> <code>[x_<wbr/>c,<wbr/> y_<wbr/>c]</code> are the coordinates to sample in the
+input image that correspond to the pixel values in the
+corrected image at the coordinate <code>[x_<wbr/>i,<wbr/> y_<wbr/>i]</code>:</p>
+<pre><code> correctedImage(x_<wbr/>i,<wbr/> y_<wbr/>i) = sample_<wbr/>at(x_<wbr/>c,<wbr/> y_<wbr/>c,<wbr/> inputImage)
+</code></pre>
+<p>The pixel coordinates are defined in a normalized
+coordinate system related to the
+<a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a> calibration fields.<wbr/>
+Both <code>[x_<wbr/>i,<wbr/> y_<wbr/>i]</code> and <code>[x_<wbr/>c,<wbr/> y_<wbr/>c]</code> have <code>(0,<wbr/>0)</code> at the
+lens optical center <code>[c_<wbr/>x,<wbr/> c_<wbr/>y]</code>.<wbr/> The maximum magnitudes
+of both x and y coordinates are normalized to be 1 at the
+edge further from the optical center,<wbr/> so the range
+for both dimensions is <code>-1 &lt;= x &lt;= 1</code>.<wbr/></p>
+<p>Finally,<wbr/> <code>r</code> represents the radial distance from the
+optical center,<wbr/> <code>r^2 = x_<wbr/>i^2 + y_<wbr/>i^2</code>,<wbr/> and its magnitude
+is therefore no larger than <code>|<wbr/>r|<wbr/> &lt;= sqrt(2)</code>.<wbr/></p>
+<p>The distortion model used is the Brown-Conrady model.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.lens.aperture">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>aperture
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired lens aperture size,<wbr/> as a ratio of lens focal length to the
+effective aperture diameter.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              The f-number (f/<wbr/>N)
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableApertures">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Apertures</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Setting this value is only supported on the camera devices that have a variable
+aperture lens.<wbr/></p>
+<p>When this is supported and <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is OFF,<wbr/>
+this can be set along with <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>,<wbr/>
+<a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>,<wbr/> and <a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a>
+to achieve manual exposure control.<wbr/></p>
+<p>The requested aperture value may take several frames to reach the
+requested value; the camera device will report the current (intermediate)
+aperture size in capture result metadata while the aperture is changing.<wbr/>
+While the aperture is still changing,<wbr/> <a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will be set to MOVING.<wbr/></p>
+<p>When this is supported and <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> is one of
+the ON modes,<wbr/> this will be overridden by the camera device
+auto-exposure algorithm,<wbr/> the overridden values are then provided
+back to the user in the corresponding result.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.filterDensity">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>filter<wbr/>Density
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired setting for the lens neutral density filter(s).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Exposure Value (EV)
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableFilterDensities">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Filter<wbr/>Densities</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control will not be supported on most camera devices.<wbr/></p>
+<p>Lens filters are typically used to lower the amount of light the
+sensor is exposed to (measured in steps of EV).<wbr/> As used here,<wbr/> an EV
+step is the standard logarithmic representation,<wbr/> which are
+non-negative,<wbr/> and inversely proportional to the amount of light
+hitting the sensor.<wbr/>  For example,<wbr/> setting this to 0 would result
+in no reduction of the incoming light,<wbr/> and setting this to 2 would
+mean that the filter is set to reduce incoming light by two stops
+(allowing 1/<wbr/>4 of the prior amount of light to the sensor).<wbr/></p>
+<p>It may take several frames before the lens filter density changes
+to the requested value.<wbr/> While the filter density is still changing,<wbr/>
+<a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will be set to MOVING.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.focalLength">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>focal<wbr/>Length
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired lens focal length; used for optical zoom.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Millimeters
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableFocalLengths">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Focal<wbr/>Lengths</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This setting controls the physical focal length of the camera
+device's lens.<wbr/> Changing the focal length changes the field of
+view of the camera device,<wbr/> and is usually used for optical zoom.<wbr/></p>
+<p>Like <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> and <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a>,<wbr/> this
+setting won't be applied instantaneously,<wbr/> and it may take several
+frames before the lens can change to the requested focal length.<wbr/>
+While the focal length is still changing,<wbr/> <a href="#dynamic_android.lens.state">android.<wbr/>lens.<wbr/>state</a> will
+be set to MOVING.<wbr/></p>
+<p>Optical zoom will not be supported on most devices.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.focusDistance">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>focus<wbr/>Distance
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Desired distance to plane of sharpest focus,<wbr/>
+measured from frontmost surface of the lens.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              See android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration for details
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Should be zero for fixed-focus cameras</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.focusRange">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>focus<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as pairFloatFloat]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+                <div class="entry_type_notes">Range of scene distances that are in focus</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The range of scene distances that are in
+sharp focus (depth of field).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              A pair of focus distances in diopters: (near,<wbr/>
+          far); see android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration for details.<wbr/>
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;=0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If variable focus not supported,<wbr/> can still report
+fixed depth of field range</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.opticalStabilizationMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Optical stabilization is unavailable.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Optical stabilization is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Sets whether the camera device uses optical image stabilization (OIS)
+when capturing images.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>OIS is used to compensate for motion blur due to small
+movements of the camera during capture.<wbr/> Unlike digital image
+stabilization (<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> OIS
+makes use of mechanical elements to stabilize the camera
+sensor,<wbr/> and thus allows for longer exposure times before
+camera shake becomes apparent.<wbr/></p>
+<p>Switching between different optical stabilization modes may take several
+frames to initialize,<wbr/> the camera device will report the current mode in
+capture result metadata.<wbr/> For example,<wbr/> When "ON" mode is requested,<wbr/> the
+optical stabilization modes in the first several capture results may still
+be "OFF",<wbr/> and it will become "ON" when the initialization is done.<wbr/></p>
+<p>If a camera device supports both OIS and digital image stabilization
+(<a href="#controls_android.control.videoStabilizationMode">android.<wbr/>control.<wbr/>video<wbr/>Stabilization<wbr/>Mode</a>),<wbr/> turning both modes on may produce undesirable
+interaction,<wbr/> so it is recommended not to enable both at the same time.<wbr/></p>
+<p>Not all devices will support OIS; see
+<a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a> for
+available controls.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.state">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>state
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">STATIONARY</span>
+                    <span class="entry_type_enum_notes"><p>The lens parameters (<a href="#controls_android.lens.focalLength">android.<wbr/>lens.<wbr/>focal<wbr/>Length</a>,<wbr/> <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a>,<wbr/>
+<a href="#controls_android.lens.filterDensity">android.<wbr/>lens.<wbr/>filter<wbr/>Density</a> and <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a>) are not changing.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MOVING</span>
+                    <span class="entry_type_enum_notes"><p>One or several of the lens parameters
+(<a href="#controls_android.lens.focalLength">android.<wbr/>lens.<wbr/>focal<wbr/>Length</a>,<wbr/> <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a>,<wbr/>
+<a href="#controls_android.lens.filterDensity">android.<wbr/>lens.<wbr/>filter<wbr/>Density</a> or <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a>) is
+currently changing.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Current lens status.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For lens parameters <a href="#controls_android.lens.focalLength">android.<wbr/>lens.<wbr/>focal<wbr/>Length</a>,<wbr/> <a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a>,<wbr/>
+<a href="#controls_android.lens.filterDensity">android.<wbr/>lens.<wbr/>filter<wbr/>Density</a> and <a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a>,<wbr/> when changes are requested,<wbr/>
+they may take several frames to reach the requested values.<wbr/> This state indicates
+the current status of the lens parameters.<wbr/></p>
+<p>When the state is STATIONARY,<wbr/> the lens parameters are not changing.<wbr/> This could be
+either because the parameters are all fixed,<wbr/> or because the lens has had enough
+time to reach the most recently-requested values.<wbr/>
+If all these lens parameters are not changable for a camera device,<wbr/> as listed below:</p>
+<ul>
+<li>Fixed focus (<code><a href="#static_android.lens.info.minimumFocusDistance">android.<wbr/>lens.<wbr/>info.<wbr/>minimum<wbr/>Focus<wbr/>Distance</a> == 0</code>),<wbr/> which means
+<a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a> parameter will always be 0.<wbr/></li>
+<li>Fixed focal length (<a href="#static_android.lens.info.availableFocalLengths">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Focal<wbr/>Lengths</a> contains single value),<wbr/>
+which means the optical zoom is not supported.<wbr/></li>
+<li>No ND filter (<a href="#static_android.lens.info.availableFilterDensities">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Filter<wbr/>Densities</a> contains only 0).<wbr/></li>
+<li>Fixed aperture (<a href="#static_android.lens.info.availableApertures">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Apertures</a> contains single value).<wbr/></li>
+</ul>
+<p>Then this state will always be STATIONARY.<wbr/></p>
+<p>When the state is MOVING,<wbr/> it indicates that at least one of the lens parameters
+is changing.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.poseRotation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>pose<wbr/>Rotation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The orientation of the camera relative to the sensor
+coordinate system.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Quaternion coefficients
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The four coefficients that describe the quaternion
+rotation from the Android sensor coordinate system to a
+camera-aligned coordinate system where the X-axis is
+aligned with the long side of the image sensor,<wbr/> the Y-axis
+is aligned with the short side of the image sensor,<wbr/> and
+the Z-axis is aligned with the optical axis of the sensor.<wbr/></p>
+<p>To convert from the quaternion coefficients <code>(x,<wbr/>y,<wbr/>z,<wbr/>w)</code>
+to the axis of rotation <code>(a_<wbr/>x,<wbr/> a_<wbr/>y,<wbr/> a_<wbr/>z)</code> and rotation
+amount <code>theta</code>,<wbr/> the following formulas can be used:</p>
+<pre><code> theta = 2 * acos(w)
+a_<wbr/>x = x /<wbr/> sin(theta/<wbr/>2)
+a_<wbr/>y = y /<wbr/> sin(theta/<wbr/>2)
+a_<wbr/>z = z /<wbr/> sin(theta/<wbr/>2)
+</code></pre>
+<p>To create a 3x3 rotation matrix that applies the rotation
+defined by this quaternion,<wbr/> the following matrix can be
+used:</p>
+<pre><code>R = [ 1 - 2y^2 - 2z^2,<wbr/>       2xy - 2zw,<wbr/>       2xz + 2yw,<wbr/>
+           2xy + 2zw,<wbr/> 1 - 2x^2 - 2z^2,<wbr/>       2yz - 2xw,<wbr/>
+           2xz - 2yw,<wbr/>       2yz + 2xw,<wbr/> 1 - 2x^2 - 2y^2 ]
+</code></pre>
+<p>This matrix can then be used to apply the rotation to a
+ column vector point with</p>
+<p><code>p' = Rp</code></p>
+<p>where <code>p</code> is in the device sensor coordinate system,<wbr/> and
+ <code>p'</code> is in the camera-oriented coordinate system.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.poseTranslation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>pose<wbr/>Translation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Position of the camera optical center.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Meters
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The position of the camera device's lens optical center,<wbr/>
+as a three-dimensional vector <code>(x,<wbr/>y,<wbr/>z)</code>,<wbr/> relative to the
+optical center of the largest camera device facing in the
+same direction as this camera,<wbr/> in the <a href="https://developer.android.com/reference/android/hardware/SensorEvent.html">Android sensor coordinate
+axes</a>.<wbr/> Note that only the axis definitions are shared with
+the sensor coordinate system,<wbr/> but not the origin.<wbr/></p>
+<p>If this device is the largest or only camera device with a
+given facing,<wbr/> then this position will be <code>(0,<wbr/> 0,<wbr/> 0)</code>; a
+camera device with a lens optical center located 3 cm from
+the main sensor along the +X axis (to the right from the
+user's perspective) will report <code>(0.<wbr/>03,<wbr/> 0,<wbr/> 0)</code>.<wbr/></p>
+<p>To transform a pixel coordinates between two cameras
+facing the same direction,<wbr/> first the source camera
+<a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a> must be corrected for.<wbr/>  Then
+the source camera <a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a> needs
+to be applied,<wbr/> followed by the <a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a>
+of the source camera,<wbr/> the translation of the source camera
+relative to the destination camera,<wbr/> the
+<a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a> of the destination camera,<wbr/> and
+finally the inverse of <a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a>
+of the destination camera.<wbr/> This obtains a
+radial-distortion-free coordinate in the destination
+camera pixel coordinates.<wbr/></p>
+<p>To compare this against a real image from the destination
+camera,<wbr/> the destination camera image then needs to be
+corrected for radial distortion before comparison or
+sampling.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.intrinsicCalibration">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  5
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The parameters for this camera device's intrinsic
+calibration.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Pixels in the
+            android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size
+            coordinate system.<wbr/>
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The five calibration parameters that describe the
+transform from camera-centric 3D coordinates to sensor
+pixel coordinates:</p>
+<pre><code>[f_<wbr/>x,<wbr/> f_<wbr/>y,<wbr/> c_<wbr/>x,<wbr/> c_<wbr/>y,<wbr/> s]
+</code></pre>
+<p>Where <code>f_<wbr/>x</code> and <code>f_<wbr/>y</code> are the horizontal and vertical
+focal lengths,<wbr/> <code>[c_<wbr/>x,<wbr/> c_<wbr/>y]</code> is the position of the optical
+axis,<wbr/> and <code>s</code> is a skew parameter for the sensor plane not
+being aligned with the lens plane.<wbr/></p>
+<p>These are typically used within a transformation matrix K:</p>
+<pre><code>K = [ f_<wbr/>x,<wbr/>   s,<wbr/> c_<wbr/>x,<wbr/>
+       0,<wbr/> f_<wbr/>y,<wbr/> c_<wbr/>y,<wbr/>
+       0    0,<wbr/>   1 ]
+</code></pre>
+<p>which can then be combined with the camera pose rotation
+<code>R</code> and translation <code>t</code> (<a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a> and
+<a href="#static_android.lens.poseTranslation">android.<wbr/>lens.<wbr/>pose<wbr/>Translation</a>,<wbr/> respective) to calculate the
+complete transform from world coordinates to pixel
+coordinates:</p>
+<pre><code>P = [ K 0   * [ R t
+     0 1 ]     0 1 ]
+</code></pre>
+<p>and with <code>p_<wbr/>w</code> being a point in the world coordinate system
+and <code>p_<wbr/>s</code> being a point in the camera active pixel array
+coordinate system,<wbr/> and with the mapping including the
+homogeneous division by z:</p>
+<pre><code> p_<wbr/>h = (x_<wbr/>h,<wbr/> y_<wbr/>h,<wbr/> z_<wbr/>h) = P p_<wbr/>w
+p_<wbr/>s = p_<wbr/>h /<wbr/> z_<wbr/>h
+</code></pre>
+<p>so <code>[x_<wbr/>s,<wbr/> y_<wbr/>s]</code> is the pixel coordinates of the world
+point,<wbr/> <code>z_<wbr/>s = 1</code>,<wbr/> and <code>w_<wbr/>s</code> is a measurement of disparity
+(depth) in pixel coordinates.<wbr/></p>
+<p>Note that the coordinate system for this transform is the
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> system,<wbr/>
+where <code>(0,<wbr/>0)</code> is the top-left of the
+preCorrectionActiveArraySize rectangle.<wbr/> Once the pose and
+intrinsic calibration transforms have been applied to a
+world point,<wbr/> then the <a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a>
+transform needs to be applied,<wbr/> and the result adjusted to
+be in the <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> coordinate
+system (where <code>(0,<wbr/> 0)</code> is the top-left of the
+activeArraySize rectangle),<wbr/> to determine the final pixel
+coordinate of the world point for processed (non-RAW)
+output buffers.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.lens.radialDistortion">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>lens.<wbr/>radial<wbr/>Distortion
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  6
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The correction coefficients to correct for this camera device's
+radial and tangential lens distortion.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+            Unitless coefficients.<wbr/>
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Four radial distortion coefficients <code>[kappa_<wbr/>0,<wbr/> kappa_<wbr/>1,<wbr/> kappa_<wbr/>2,<wbr/>
+kappa_<wbr/>3]</code> and two tangential distortion coefficients
+<code>[kappa_<wbr/>4,<wbr/> kappa_<wbr/>5]</code> that can be used to correct the
+lens's geometric distortion with the mapping equations:</p>
+<pre><code> x_<wbr/>c = x_<wbr/>i * ( kappa_<wbr/>0 + kappa_<wbr/>1 * r^2 + kappa_<wbr/>2 * r^4 + kappa_<wbr/>3 * r^6 ) +
+       kappa_<wbr/>4 * (2 * x_<wbr/>i * y_<wbr/>i) + kappa_<wbr/>5 * ( r^2 + 2 * x_<wbr/>i^2 )
+ y_<wbr/>c = y_<wbr/>i * ( kappa_<wbr/>0 + kappa_<wbr/>1 * r^2 + kappa_<wbr/>2 * r^4 + kappa_<wbr/>3 * r^6 ) +
+       kappa_<wbr/>5 * (2 * x_<wbr/>i * y_<wbr/>i) + kappa_<wbr/>4 * ( r^2 + 2 * y_<wbr/>i^2 )
+</code></pre>
+<p>Here,<wbr/> <code>[x_<wbr/>c,<wbr/> y_<wbr/>c]</code> are the coordinates to sample in the
+input image that correspond to the pixel values in the
+corrected image at the coordinate <code>[x_<wbr/>i,<wbr/> y_<wbr/>i]</code>:</p>
+<pre><code> correctedImage(x_<wbr/>i,<wbr/> y_<wbr/>i) = sample_<wbr/>at(x_<wbr/>c,<wbr/> y_<wbr/>c,<wbr/> inputImage)
+</code></pre>
+<p>The pixel coordinates are defined in a normalized
+coordinate system related to the
+<a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a> calibration fields.<wbr/>
+Both <code>[x_<wbr/>i,<wbr/> y_<wbr/>i]</code> and <code>[x_<wbr/>c,<wbr/> y_<wbr/>c]</code> have <code>(0,<wbr/>0)</code> at the
+lens optical center <code>[c_<wbr/>x,<wbr/> c_<wbr/>y]</code>.<wbr/> The maximum magnitudes
+of both x and y coordinates are normalized to be 1 at the
+edge further from the optical center,<wbr/> so the range
+for both dimensions is <code>-1 &lt;= x &lt;= 1</code>.<wbr/></p>
+<p>Finally,<wbr/> <code>r</code> represents the radial distance from the
+optical center,<wbr/> <code>r^2 = x_<wbr/>i^2 + y_<wbr/>i^2</code>,<wbr/> and its magnitude
+is therefore no larger than <code>|<wbr/>r|<wbr/> &lt;= sqrt(2)</code>.<wbr/></p>
+<p>The distortion model used is the Brown-Conrady model.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_noiseReduction" class="section">noiseReduction</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.noiseReduction.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>noise<wbr/>Reduction.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No noise reduction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Noise reduction is applied without reducing frame rate relative to sensor
+output.<wbr/> It may be the same as OFF if noise reduction will reduce frame rate
+relative to sensor.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality noise reduction is applied,<wbr/> at the cost of possibly reduced frame
+rate relative to sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MINIMAL</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>MINIMAL noise reduction is applied without reducing frame rate relative to
+sensor output.<wbr/> </p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Noise reduction is applied at different levels for different output streams,<wbr/>
+based on resolution.<wbr/> Streams at maximum recording resolution (see <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">CameraDevice#createCaptureSession</a>) or below have noise
+reduction applied,<wbr/> while higher-resolution streams have MINIMAL (if supported) or no
+noise reduction applied (if MINIMAL is not supported.<wbr/>) The degree of noise reduction
+for low-resolution streams is tuned so that frame rate is not impacted,<wbr/> and the quality
+is equal to or better than FAST (since it is only applied to lower-resolution outputs,<wbr/>
+quality may improve from FAST).<wbr/></p>
+<p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
+with YUV or PRIVATE reprocessing,<wbr/> where the application continuously captures
+high-resolution intermediate buffers into a circular buffer,<wbr/> from which a final image is
+produced via reprocessing when a user takes a picture.<wbr/>  For such a use case,<wbr/> the
+high-resolution buffers must not have noise reduction applied to maximize efficiency of
+preview and to avoid over-applying noise filtering when reprocessing,<wbr/> while
+low-resolution buffers (used for recording or preview,<wbr/> generally) need noise reduction
+applied for reasonable preview quality.<wbr/></p>
+<p>This mode is guaranteed to be supported by devices that support either the
+YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING capabilities
+(<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> lists either of those capabilities) and it will
+be the default mode for CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Mode of operation for the noise reduction algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The noise reduction algorithm attempts to improve image quality by removing
+excessive noise added by the capture process,<wbr/> especially in dark conditions.<wbr/></p>
+<p>OFF means no noise reduction will be applied by the camera device,<wbr/> for both raw and
+YUV domain.<wbr/></p>
+<p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,<wbr/>to remove
+demosaicing or other processing artifacts.<wbr/> For YUV_<wbr/>REPROCESSING,<wbr/> MINIMAL is same as OFF.<wbr/>
+This mode is optional,<wbr/> may not be support by all devices.<wbr/> The application should check
+<a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a> before using it.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean camera device determined noise filtering
+will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the camera device
+will use the highest-quality noise filtering algorithms,<wbr/>
+even if it slows down capture rate.<wbr/> FAST means the camera device will not
+slow down capture rate when applying noise filtering.<wbr/> FAST may be the same as MINIMAL if
+MINIMAL is listed,<wbr/> or the same as OFF if any noise filtering will slow down capture rate.<wbr/>
+Every output stream will have a similar amount of enhancement applied.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG is meant to be used by applications that maintain a continuous circular
+buffer of high-resolution images during preview and reprocess image(s) from that buffer
+into a final capture when triggered by the user.<wbr/> In this mode,<wbr/> the camera device applies
+noise reduction to low-resolution streams (below maximum recording resolution) to maximize
+preview quality,<wbr/> but does not apply noise reduction to high-resolution streams,<wbr/> since
+those will be reprocessed later if necessary.<wbr/></p>
+<p>For YUV_<wbr/>REPROCESSING,<wbr/> these FAST/<wbr/>HIGH_<wbr/>QUALITY modes both mean that the camera device
+will apply FAST/<wbr/>HIGH_<wbr/>QUALITY YUV domain noise reduction,<wbr/> respectively.<wbr/> The camera device
+may adjust the noise reduction parameters for best image quality based on the
+<a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> if it is set.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For YUV_<wbr/>REPROCESSING The HAL can use <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> to
+adjust the internal noise reduction parameters appropriately to get the best quality
+images.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.noiseReduction.strength">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>noise<wbr/>Reduction.<wbr/>strength
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Control the amount of noise reduction
+applied to the images</p>
+            </td>
+
+            <td class="entry_units">
+              1-10; 10 is max noise reduction
+            </td>
+
+            <td class="entry_range">
+              <p>1 - 10</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.noiseReduction.availableNoiseReductionModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of noise reduction modes for <a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a> that are supported
+by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Full-capability camera devices will always support OFF and FAST.<wbr/></p>
+<p>Camera devices that support YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING will support
+ZERO_<wbr/>SHUTTER_<wbr/>LAG.<wbr/></p>
+<p>Legacy-capability camera devices will only support FAST mode.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if noise reduction control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.noiseReduction.mode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>noise<wbr/>Reduction.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No noise reduction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Noise reduction is applied without reducing frame rate relative to sensor
+output.<wbr/> It may be the same as OFF if noise reduction will reduce frame rate
+relative to sensor.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality noise reduction is applied,<wbr/> at the cost of possibly reduced frame
+rate relative to sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MINIMAL</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>MINIMAL noise reduction is applied without reducing frame rate relative to
+sensor output.<wbr/> </p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ZERO_SHUTTER_LAG</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Noise reduction is applied at different levels for different output streams,<wbr/>
+based on resolution.<wbr/> Streams at maximum recording resolution (see <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">CameraDevice#createCaptureSession</a>) or below have noise
+reduction applied,<wbr/> while higher-resolution streams have MINIMAL (if supported) or no
+noise reduction applied (if MINIMAL is not supported.<wbr/>) The degree of noise reduction
+for low-resolution streams is tuned so that frame rate is not impacted,<wbr/> and the quality
+is equal to or better than FAST (since it is only applied to lower-resolution outputs,<wbr/>
+quality may improve from FAST).<wbr/></p>
+<p>This mode is intended to be used by applications operating in a zero-shutter-lag mode
+with YUV or PRIVATE reprocessing,<wbr/> where the application continuously captures
+high-resolution intermediate buffers into a circular buffer,<wbr/> from which a final image is
+produced via reprocessing when a user takes a picture.<wbr/>  For such a use case,<wbr/> the
+high-resolution buffers must not have noise reduction applied to maximize efficiency of
+preview and to avoid over-applying noise filtering when reprocessing,<wbr/> while
+low-resolution buffers (used for recording or preview,<wbr/> generally) need noise reduction
+applied for reasonable preview quality.<wbr/></p>
+<p>This mode is guaranteed to be supported by devices that support either the
+YUV_<wbr/>REPROCESSING or PRIVATE_<wbr/>REPROCESSING capabilities
+(<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> lists either of those capabilities) and it will
+be the default mode for CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Mode of operation for the noise reduction algorithm.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The noise reduction algorithm attempts to improve image quality by removing
+excessive noise added by the capture process,<wbr/> especially in dark conditions.<wbr/></p>
+<p>OFF means no noise reduction will be applied by the camera device,<wbr/> for both raw and
+YUV domain.<wbr/></p>
+<p>MINIMAL means that only sensor raw domain basic noise reduction is enabled ,<wbr/>to remove
+demosaicing or other processing artifacts.<wbr/> For YUV_<wbr/>REPROCESSING,<wbr/> MINIMAL is same as OFF.<wbr/>
+This mode is optional,<wbr/> may not be support by all devices.<wbr/> The application should check
+<a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a> before using it.<wbr/></p>
+<p>FAST/<wbr/>HIGH_<wbr/>QUALITY both mean camera device determined noise filtering
+will be applied.<wbr/> HIGH_<wbr/>QUALITY mode indicates that the camera device
+will use the highest-quality noise filtering algorithms,<wbr/>
+even if it slows down capture rate.<wbr/> FAST means the camera device will not
+slow down capture rate when applying noise filtering.<wbr/> FAST may be the same as MINIMAL if
+MINIMAL is listed,<wbr/> or the same as OFF if any noise filtering will slow down capture rate.<wbr/>
+Every output stream will have a similar amount of enhancement applied.<wbr/></p>
+<p>ZERO_<wbr/>SHUTTER_<wbr/>LAG is meant to be used by applications that maintain a continuous circular
+buffer of high-resolution images during preview and reprocess image(s) from that buffer
+into a final capture when triggered by the user.<wbr/> In this mode,<wbr/> the camera device applies
+noise reduction to low-resolution streams (below maximum recording resolution) to maximize
+preview quality,<wbr/> but does not apply noise reduction to high-resolution streams,<wbr/> since
+those will be reprocessed later if necessary.<wbr/></p>
+<p>For YUV_<wbr/>REPROCESSING,<wbr/> these FAST/<wbr/>HIGH_<wbr/>QUALITY modes both mean that the camera device
+will apply FAST/<wbr/>HIGH_<wbr/>QUALITY YUV domain noise reduction,<wbr/> respectively.<wbr/> The camera device
+may adjust the noise reduction parameters for best image quality based on the
+<a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> if it is set.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For YUV_<wbr/>REPROCESSING The HAL can use <a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a> to
+adjust the internal noise reduction parameters appropriately to get the best quality
+images.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_quirks" class="section">quirks</td></tr>
+
+
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.quirks.meteringCropRegion">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>quirks.<wbr/>metering<wbr/>Crop<wbr/>Region
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>If set to 1,<wbr/> the camera service does not
+scale 'normalized' coordinates with respect to the crop
+region.<wbr/> This applies to metering input (a{e,<wbr/>f,<wbr/>wb}Region
+and output (face rectangles).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Normalized coordinates refer to those in the
+(-1000,<wbr/>1000) range mentioned in the
+android.<wbr/>hardware.<wbr/>Camera API.<wbr/></p>
+<p>HAL implementations should instead always use and emit
+sensor array-relative coordinates for all region data.<wbr/> Does
+not need to be listed in static metadata.<wbr/> Support will be
+removed in future versions of camera service.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.quirks.triggerAfWithAuto">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>quirks.<wbr/>trigger<wbr/>Af<wbr/>With<wbr/>Auto
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>If set to 1,<wbr/> then the camera service always
+switches to FOCUS_<wbr/>MODE_<wbr/>AUTO before issuing a AF
+trigger.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL implementations should implement AF trigger
+modes for AUTO,<wbr/> MACRO,<wbr/> CONTINUOUS_<wbr/>FOCUS,<wbr/> and
+CONTINUOUS_<wbr/>PICTURE modes instead of using this flag.<wbr/> Does
+not need to be listed in static metadata.<wbr/> Support will be
+removed in future versions of camera service</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.quirks.useZslFormat">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>quirks.<wbr/>use<wbr/>Zsl<wbr/>Format
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>If set to 1,<wbr/> the camera service uses
+CAMERA2_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>ZSL instead of
+HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>IMPLEMENTATION_<wbr/>DEFINED for the zero
+shutter lag stream</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL implementations should use gralloc usage flags
+to determine that a stream will be used for
+zero-shutter-lag,<wbr/> instead of relying on an explicit
+format setting.<wbr/> Does not need to be listed in static
+metadata.<wbr/> Support will be removed in future versions of
+camera service.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.quirks.usePartialResult">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="5">
+              android.<wbr/>quirks.<wbr/>use<wbr/>Partial<wbr/>Result
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>If set to 1,<wbr/> the HAL will always split result
+metadata for a single capture into multiple buffers,<wbr/>
+returned using multiple process_<wbr/>capture_<wbr/>result calls.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Does not need to be listed in static
+metadata.<wbr/> Support for partial results will be reworked in
+future versions of camera service.<wbr/> This quirk will stop
+working at that point; DO NOT USE without careful
+consideration of future support.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Refer to <code>camera3_<wbr/>capture_<wbr/>result::partial_<wbr/>result</code>
+for information on how to implement partial results.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.quirks.partialResult">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="5">
+              android.<wbr/>quirks.<wbr/>partial<wbr/>Result
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [hidden as boolean]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FINAL</span>
+                    <span class="entry_type_enum_notes"><p>The last or only metadata result buffer
+for this capture.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PARTIAL</span>
+                    <span class="entry_type_enum_notes"><p>A partial buffer of result metadata for this
+capture.<wbr/> More result buffers for this capture will be sent
+by the camera device,<wbr/> the last of which will be marked
+FINAL.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether a result given to the framework is the
+final one for the capture,<wbr/> or only a partial that contains a
+subset of the full set of dynamic metadata
+values.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>Optional.<wbr/> Default value is FINAL.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The entries in the result metadata buffers for a
+single capture may not overlap,<wbr/> except for this entry.<wbr/> The
+FINAL buffers must retain FIFO ordering relative to the
+requests that generate them,<wbr/> so the FINAL buffer for frame 3 must
+always be sent to the framework after the FINAL buffer for frame 2,<wbr/> and
+before the FINAL buffer for frame 4.<wbr/> PARTIAL buffers may be returned
+in any order relative to other frames,<wbr/> but all PARTIAL buffers for a given
+capture must arrive before the FINAL buffer for that capture.<wbr/> This entry may
+only be used by the camera device if quirks.<wbr/>usePartialResult is set to 1.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Refer to <code>camera3_<wbr/>capture_<wbr/>result::partial_<wbr/>result</code>
+for information on how to implement partial results.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_request" class="section">request</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.request.frameCount">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>frame<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A frame counter set by the framework.<wbr/> Must
+be maintained unchanged in output frame.<wbr/> This value monotonically
+increases with every new result (that is,<wbr/> each new result has a unique
+frameCount value).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              incrementing integer
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>Any int.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.request.id">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>id
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>An application-specified ID for the current
+request.<wbr/> Must be maintained unchanged in output
+frame</p>
+            </td>
+
+            <td class="entry_units">
+              arbitrary integer assigned by application
+            </td>
+
+            <td class="entry_range">
+              <p>Any int</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.request.inputStreams">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>input<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List which camera reprocess stream is used
+for the source of reprocessing data.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              List of camera reprocess stream IDs
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>Typically,<wbr/> only one entry allowed,<wbr/> must be a valid reprocess stream ID.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only meaningful when <a href="#controls_android.request.type">android.<wbr/>request.<wbr/>type</a> ==
+REPROCESS.<wbr/> Ignored otherwise</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.request.metadataMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>metadata<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">NONE</span>
+                    <span class="entry_type_enum_notes"><p>No metadata should be produced on output,<wbr/> except
+for application-bound buffer data.<wbr/> If no
+application-bound streams exist,<wbr/> no frame should be
+placed in the output frame queue.<wbr/> If such streams
+exist,<wbr/> a frame should be placed on the output queue
+with null metadata but with the necessary output buffer
+information.<wbr/> Timestamp information should still be
+included with any output stream buffers</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FULL</span>
+                    <span class="entry_type_enum_notes"><p>All metadata should be produced.<wbr/> Statistics will
+only be produced if they are separately
+enabled</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>How much metadata to produce on
+output</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.request.outputStreams">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>output<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Lists which camera output streams image data
+from this capture must be sent to</p>
+            </td>
+
+            <td class="entry_units">
+              List of camera stream IDs
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>List must only include streams that have been
+created</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If no output streams are listed,<wbr/> then the image
+data should simply be discarded.<wbr/> The image data must
+still be captured for metadata and statistics production,<wbr/>
+and the lens and flash must operate as requested.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.request.type">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>type
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CAPTURE</span>
+                    <span class="entry_type_enum_notes"><p>Capture a new image from the imaging hardware,<wbr/>
+and process it according to the
+settings</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">REPROCESS</span>
+                    <span class="entry_type_enum_notes"><p>Process previously captured data; the
+<a href="#controls_android.request.inputStreams">android.<wbr/>request.<wbr/>input<wbr/>Streams</a> parameter determines the
+source reprocessing stream.<wbr/> TODO: Mark dynamic metadata
+needed for reprocessing with [RP]</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The type of the request; either CAPTURE or
+REPROCESS.<wbr/> For HAL3,<wbr/> this tag is redundant.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.request.maxNumOutputStreams">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum numbers of different types of output streams
+that can be configured and used simultaneously by a camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>For processed (and stalling) format streams,<wbr/> &gt;= 1.<wbr/></p>
+<p>For Raw format (either stalling or non-stalling) streams,<wbr/> &gt;= 0.<wbr/></p>
+<p>For processed (but not stalling) format streams,<wbr/> &gt;= 3
+for FULL mode devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL</code>);
+&gt;= 2 for LIMITED mode devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == LIMITED</code>).<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is a 3 element tuple that contains the max number of output simultaneous
+streams for raw sensor,<wbr/> processed (but not stalling),<wbr/> and processed (and stalling)
+formats respectively.<wbr/> For example,<wbr/> assuming that JPEG is typically a processed and
+stalling stream,<wbr/> if max raw sensor format output stream number is 1,<wbr/> max YUV streams
+number is 3,<wbr/> and max JPEG stream number is 2,<wbr/> then this tuple should be <code>(1,<wbr/> 3,<wbr/> 2)</code>.<wbr/></p>
+<p>This lists the upper bound of the number of output streams supported by
+the camera device.<wbr/> Using more streams simultaneously may require more hardware and
+CPU resources that will consume more power.<wbr/> The image format for an output stream can
+be any supported format provided by <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a>.<wbr/>
+The formats defined in <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> can be catergorized
+into the 3 stream types as below:</p>
+<ul>
+<li>Processed (but stalling): any non-RAW format with a stallDurations &gt; 0.<wbr/>
+  Typically <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">JPEG format</a>.<wbr/></li>
+<li>Raw formats: <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_SENSOR">RAW_<wbr/>SENSOR</a>,<wbr/> <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW10">RAW10</a>,<wbr/> or <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW12">RAW12</a>.<wbr/></li>
+<li>Processed (but not-stalling): any non-RAW format without a stall duration.<wbr/>
+  Typically <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">YUV_<wbr/>420_<wbr/>888</a>,<wbr/>
+  <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">NV21</a>,<wbr/> or
+  <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12">YV12</a>.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.maxNumOutputRaw">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Raw
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum numbers of different types of output streams
+that can be configured and used simultaneously by a camera device
+for any <code>RAW</code> formats.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value contains the max number of output simultaneous
+streams from the raw sensor.<wbr/></p>
+<p>This lists the upper bound of the number of output streams supported by
+the camera device.<wbr/> Using more streams simultaneously may require more hardware and
+CPU resources that will consume more power.<wbr/> The image format for this kind of an output stream can
+be any <code>RAW</code> and supported format provided by <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a>.<wbr/></p>
+<p>In particular,<wbr/> a <code>RAW</code> format is typically one of:</p>
+<ul>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_SENSOR">RAW_<wbr/>SENSOR</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW10">RAW10</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW12">RAW12</a></li>
+</ul>
+<p>LEGACY mode devices (<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> <code>==</code> LEGACY)
+never support raw streams.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.maxNumOutputProc">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Proc
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum numbers of different types of output streams
+that can be configured and used simultaneously by a camera device
+for any processed (but not-stalling) formats.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 3
+for FULL mode devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL</code>);
+&gt;= 2 for LIMITED mode devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == LIMITED</code>).<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value contains the max number of output simultaneous
+streams for any processed (but not-stalling) formats.<wbr/></p>
+<p>This lists the upper bound of the number of output streams supported by
+the camera device.<wbr/> Using more streams simultaneously may require more hardware and
+CPU resources that will consume more power.<wbr/> The image format for this kind of an output stream can
+be any non-<code>RAW</code> and supported format provided by <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a>.<wbr/></p>
+<p>Processed (but not-stalling) is defined as any non-RAW format without a stall duration.<wbr/>
+Typically:</p>
+<ul>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">YUV_<wbr/>420_<wbr/>888</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#NV21">NV21</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12">YV12</a></li>
+<li>Implementation-defined formats,<wbr/> i.<wbr/>e.<wbr/> <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#isOutputSupportedFor(Class)">StreamConfigurationMap#isOutputSupportedFor(Class)</a></li>
+</ul>
+<p>For full guarantees,<wbr/> query <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a> with a
+processed format -- it will return 0 for a non-stalling stream.<wbr/></p>
+<p>LEGACY devices will support at least 2 processing/<wbr/>non-stalling streams.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.maxNumOutputProcStalling">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Proc<wbr/>Stalling
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum numbers of different types of output streams
+that can be configured and used simultaneously by a camera device
+for any processed (and stalling) formats.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value contains the max number of output simultaneous
+streams for any processed (but not-stalling) formats.<wbr/></p>
+<p>This lists the upper bound of the number of output streams supported by
+the camera device.<wbr/> Using more streams simultaneously may require more hardware and
+CPU resources that will consume more power.<wbr/> The image format for this kind of an output stream can
+be any non-<code>RAW</code> and supported format provided by <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a>.<wbr/></p>
+<p>A processed and stalling format is defined as any non-RAW format with a stallDurations
+&gt; 0.<wbr/>  Typically only the <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">JPEG format</a> is a
+stalling format.<wbr/></p>
+<p>For full guarantees,<wbr/> query <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a> with a
+processed format -- it will return a non-0 value for a stalling stream.<wbr/></p>
+<p>LEGACY devices will support up to 1 processing/<wbr/>stalling stream.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.maxNumReprocessStreams">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Reprocess<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  1
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>How many reprocessing streams of any type
+can be allocated at the same time.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only used by HAL2.<wbr/>x.<wbr/></p>
+<p>When set to 0,<wbr/> it means no reprocess stream is supported.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.maxNumInputStreams">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Input<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum numbers of any type of input streams
+that can be configured and used simultaneously by a camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>0 or 1.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to 0,<wbr/> it means no input stream is supported.<wbr/></p>
+<p>The image format for a input stream can be any supported format returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputFormats">StreamConfigurationMap#getInputFormats</a>.<wbr/> When using an
+input stream,<wbr/> there must be at least one output stream configured to to receive the
+reprocessed images.<wbr/></p>
+<p>When an input stream and some output streams are used in a reprocessing request,<wbr/>
+only the input buffer will be used to produce these output stream buffers,<wbr/> and a
+new sensor image will not be captured.<wbr/></p>
+<p>For example,<wbr/> for Zero Shutter Lag (ZSL) still capture use case,<wbr/> the input
+stream image format will be PRIVATE,<wbr/> the associated output stream image format
+should be JPEG.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For the reprocessing flow and controls,<wbr/> see
+hardware/<wbr/>libhardware/<wbr/>include/<wbr/>hardware/<wbr/>camera3.<wbr/>h Section 10 for more details.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.pipelineMaxDepth">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>pipeline<wbr/>Max<wbr/>Depth
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Specifies the number of maximum pipeline stages a frame
+has to go through from when it's exposed to when it's available
+to the framework.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A typical minimum value for this is 2 (one stage to expose,<wbr/>
+one stage to readout) from the sensor.<wbr/> The ISP then usually adds
+its own stages to do custom HW processing.<wbr/> Further stages may be
+added by SW processing.<wbr/></p>
+<p>Depending on what settings are used (e.<wbr/>g.<wbr/> YUV,<wbr/> JPEG) and what
+processing is enabled (e.<wbr/>g.<wbr/> face detection),<wbr/> the actual pipeline
+depth (specified by <a href="#dynamic_android.request.pipelineDepth">android.<wbr/>request.<wbr/>pipeline<wbr/>Depth</a>) may be less than
+the max pipeline depth.<wbr/></p>
+<p>A pipeline depth of X stages is equivalent to a pipeline latency of
+X frame intervals.<wbr/></p>
+<p>This value will normally be 8 or less,<wbr/> however,<wbr/> for high speed capture session,<wbr/>
+the max pipeline depth will be up to 8 x size of high speed capture request list.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value should be 4 or less,<wbr/> expect for the high speed recording session,<wbr/> where the
+max batch sizes may be larger than 1.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.partialResultCount">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>partial<wbr/>Result<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Defines how many sub-components
+a result will be composed of.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>In order to combat the pipeline latency,<wbr/> partial results
+may be delivered to the application layer from the camera device as
+soon as they are available.<wbr/></p>
+<p>Optional; defaults to 1.<wbr/> A value of 1 means that partial
+results are not supported,<wbr/> and only the final TotalCaptureResult will
+be produced by the camera device.<wbr/></p>
+<p>A typical use case for this might be: after requesting an
+auto-focus (AF) lock the new AF state might be available 50%
+of the way through the pipeline.<wbr/>  The camera device could
+then immediately dispatch this state via a partial result to
+the application,<wbr/> and the rest of the metadata via later
+partial results.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.availableCapabilities">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>available<wbr/>Capabilities
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">BACKWARD_COMPATIBLE</span>
+                    <span class="entry_type_enum_notes"><p>The minimal set of capabilities that every camera
+device (regardless of <a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a>)
+supports.<wbr/></p>
+<p>This capability is listed by all normal devices,<wbr/> and
+indicates that the camera device has a feature set
+that's comparable to the baseline requirements for the
+older android.<wbr/>hardware.<wbr/>Camera API.<wbr/></p>
+<p>Devices with the DEPTH_<wbr/>OUTPUT capability might not list this
+capability,<wbr/> indicating that they support only depth measurement,<wbr/>
+not standard color output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MANUAL_SENSOR</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device can be manually controlled (3A algorithms such
+as auto-exposure,<wbr/> and auto-focus can be bypassed).<wbr/>
+The camera device supports basic manual control of the sensor image
+acquisition related stages.<wbr/> This means the following controls are
+guaranteed to be supported:</p>
+<ul>
+<li>Manual frame duration control<ul>
+<li><a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a></li>
+<li><a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+</ul>
+</li>
+<li>Manual exposure control<ul>
+<li><a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a></li>
+<li><a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
+</ul>
+</li>
+<li>Manual sensitivity control<ul>
+<li><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></li>
+<li><a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a></li>
+</ul>
+</li>
+<li>Manual lens control (if the lens is adjustable)<ul>
+<li>android.<wbr/>lens.<wbr/>*</li>
+</ul>
+</li>
+<li>Manual flash control (if a flash unit is present)<ul>
+<li>android.<wbr/>flash.<wbr/>*</li>
+</ul>
+</li>
+<li>Manual black level locking<ul>
+<li><a href="#controls_android.blackLevel.lock">android.<wbr/>black<wbr/>Level.<wbr/>lock</a></li>
+</ul>
+</li>
+<li>Auto exposure lock<ul>
+<li><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a></li>
+</ul>
+</li>
+</ul>
+<p>If any of the above 3A algorithms are enabled,<wbr/> then the camera
+device will accurately report the values applied by 3A in the
+result.<wbr/></p>
+<p>A given camera device may also support additional manual sensor controls,<wbr/>
+but this capability only covers the above list of controls.<wbr/></p>
+<p>If this is supported,<wbr/> <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> will
+additionally return a min frame duration that is greater than
+zero for each supported size-format combination.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">MANUAL_POST_PROCESSING</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device post-processing stages can be manually controlled.<wbr/>
+The camera device supports basic manual control of the image post-processing
+stages.<wbr/> This means the following controls are guaranteed to be supported:</p>
+<ul>
+<li>
+<p>Manual tonemap control</p>
+<ul>
+<li><a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a></li>
+<li><a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a></li>
+<li><a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a></li>
+<li><a href="#controls_android.tonemap.gamma">android.<wbr/>tonemap.<wbr/>gamma</a></li>
+<li><a href="#controls_android.tonemap.presetCurve">android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve</a></li>
+</ul>
+</li>
+<li>
+<p>Manual white balance control</p>
+<ul>
+<li><a href="#controls_android.colorCorrection.transform">android.<wbr/>color<wbr/>Correction.<wbr/>transform</a></li>
+<li><a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a></li>
+</ul>
+</li>
+<li>Manual lens shading map control<ul>
+<li><a href="#controls_android.shading.mode">android.<wbr/>shading.<wbr/>mode</a></li>
+<li><a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a></li>
+<li><a href="#dynamic_android.statistics.lensShadingMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map</a></li>
+<li><a href="#static_android.lens.info.shadingMapSize">android.<wbr/>lens.<wbr/>info.<wbr/>shading<wbr/>Map<wbr/>Size</a></li>
+</ul>
+</li>
+<li>Manual aberration correction control (if aberration correction is supported)<ul>
+<li><a href="#controls_android.colorCorrection.aberrationMode">android.<wbr/>color<wbr/>Correction.<wbr/>aberration<wbr/>Mode</a></li>
+<li><a href="#static_android.colorCorrection.availableAberrationModes">android.<wbr/>color<wbr/>Correction.<wbr/>available<wbr/>Aberration<wbr/>Modes</a></li>
+</ul>
+</li>
+<li>Auto white balance lock<ul>
+<li><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a></li>
+</ul>
+</li>
+</ul>
+<p>If auto white balance is enabled,<wbr/> then the camera device
+will accurately report the values applied by AWB in the result.<wbr/></p>
+<p>A given camera device may also support additional post-processing
+controls,<wbr/> but this capability only covers the above list of controls.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">RAW</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports outputting RAW buffers and
+metadata for interpreting them.<wbr/></p>
+<p>Devices supporting the RAW capability allow both for
+saving DNG files,<wbr/> and for direct application processing of
+raw sensor images.<wbr/></p>
+<ul>
+<li>RAW_<wbr/>SENSOR is supported as an output format.<wbr/></li>
+<li>The maximum available resolution for RAW_<wbr/>SENSOR streams
+  will match either the value in
+  <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a> or
+  <a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>.<wbr/></li>
+<li>All DNG-related optional metadata entries are provided
+  by the camera device.<wbr/></li>
+</ul></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PRIVATE_REPROCESSING</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports the Zero Shutter Lag reprocessing use case.<wbr/></p>
+<ul>
+<li>One input stream is supported,<wbr/> that is,<wbr/> <code><a href="#static_android.request.maxNumInputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Input<wbr/>Streams</a> == 1</code>.<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> is supported as an output/<wbr/>input format,<wbr/>
+  that is,<wbr/> <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> is included in the lists of
+  formats returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputFormats">StreamConfigurationMap#getInputFormats</a> and <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputFormats">StreamConfigurationMap#getOutputFormats</a>.<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getValidOutputFormatsForInput">StreamConfigurationMap#getValidOutputFormatsForInput</a>
+  returns non empty int[] for each supported input format returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputFormats">StreamConfigurationMap#getInputFormats</a>.<wbr/></li>
+<li>Each size returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputSizes">getInputSizes(ImageFormat.<wbr/>PRIVATE)</a> is also included in <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes">getOutputSizes(ImageFormat.<wbr/>PRIVATE)</a></li>
+<li>Using <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> does not cause a frame rate drop
+  relative to the sensor's maximum capture rate (at that resolution).<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> will be reprocessable into both
+  <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> and
+  <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a> formats.<wbr/></li>
+<li>The maximum available resolution for PRIVATE streams
+  (both input/<wbr/>output) will match the maximum available
+  resolution of JPEG streams.<wbr/></li>
+<li>Static metadata <a href="#static_android.reprocess.maxCaptureStall">android.<wbr/>reprocess.<wbr/>max<wbr/>Capture<wbr/>Stall</a>.<wbr/></li>
+<li>Only below controls are effective for reprocessing requests and
+  will be present in capture results,<wbr/> other controls in reprocess
+  requests will be ignored by the camera device.<wbr/><ul>
+<li>android.<wbr/>jpeg.<wbr/>*</li>
+<li><a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a></li>
+<li><a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a></li>
+</ul>
+</li>
+<li><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a> and
+  <a href="#static_android.edge.availableEdgeModes">android.<wbr/>edge.<wbr/>available<wbr/>Edge<wbr/>Modes</a> will both list ZERO_<wbr/>SHUTTER_<wbr/>LAG as a supported mode.<wbr/></li>
+</ul></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">READ_SENSOR_SETTINGS</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports accurately reporting the sensor settings for many of
+the sensor controls while the built-in 3A algorithm is running.<wbr/>  This allows
+reporting of sensor settings even when these settings cannot be manually changed.<wbr/></p>
+<p>The values reported for the following controls are guaranteed to be available
+in the CaptureResult,<wbr/> including when 3A is enabled:</p>
+<ul>
+<li>Exposure control<ul>
+<li><a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a></li>
+</ul>
+</li>
+<li>Sensitivity control<ul>
+<li><a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a></li>
+</ul>
+</li>
+<li>Lens controls (if the lens is adjustable)<ul>
+<li><a href="#controls_android.lens.focusDistance">android.<wbr/>lens.<wbr/>focus<wbr/>Distance</a></li>
+<li><a href="#controls_android.lens.aperture">android.<wbr/>lens.<wbr/>aperture</a></li>
+</ul>
+</li>
+</ul>
+<p>This capability is a subset of the MANUAL_<wbr/>SENSOR control capability,<wbr/> and will
+always be included if the MANUAL_<wbr/>SENSOR capability is available.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BURST_CAPTURE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports capturing high-resolution images at &gt;= 20 frames per
+second,<wbr/> in at least the uncompressed YUV format,<wbr/> when post-processing settings are set
+to FAST.<wbr/> Additionally,<wbr/> maximum-resolution images can be captured at &gt;= 10 frames
+per second.<wbr/>  Here,<wbr/> 'high resolution' means at least 8 megapixels,<wbr/> or the maximum
+resolution of the device,<wbr/> whichever is smaller.<wbr/></p>
+<p>More specifically,<wbr/> this means that a size matching the camera device's active array
+size is listed as a supported size for the <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> format in either <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes">StreamConfigurationMap#getOutputSizes</a> or <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighResolutionOutputSizes">StreamConfigurationMap#getHighResolutionOutputSizes</a>,<wbr/>
+with a minimum frame duration for that format and size of either &lt;= 1/<wbr/>20 s,<wbr/> or
+&lt;= 1/<wbr/>10 s,<wbr/> respectively; and the <a href="#static_android.control.aeAvailableTargetFpsRanges">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Target<wbr/>Fps<wbr/>Ranges</a> entry
+lists at least one FPS range where the minimum FPS is &gt;= 1 /<wbr/> minimumFrameDuration
+for the maximum-size YUV_<wbr/>420_<wbr/>888 format.<wbr/>  If that maximum size is listed in <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighResolutionOutputSizes">StreamConfigurationMap#getHighResolutionOutputSizes</a>,<wbr/>
+then the list of resolutions for YUV_<wbr/>420_<wbr/>888 from <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes">StreamConfigurationMap#getOutputSizes</a> contains at
+least one resolution &gt;= 8 megapixels,<wbr/> with a minimum frame duration of &lt;= 1/<wbr/>20
+s.<wbr/></p>
+<p>If the device supports the <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW10">ImageFormat#RAW10</a>,<wbr/> <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW12">ImageFormat#RAW12</a>,<wbr/> then those can also be captured at the same rate
+as the maximum-size YUV_<wbr/>420_<wbr/>888 resolution is.<wbr/></p>
+<p>If the device supports the PRIVATE_<wbr/>REPROCESSING capability,<wbr/> then the same guarantees
+as for the YUV_<wbr/>420_<wbr/>888 format also apply to the <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> format.<wbr/></p>
+<p>In addition,<wbr/> the <a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> field is guaranted to have a value between 0
+and 4,<wbr/> inclusive.<wbr/> <a href="#static_android.control.aeLockAvailable">android.<wbr/>control.<wbr/>ae<wbr/>Lock<wbr/>Available</a> and <a href="#static_android.control.awbLockAvailable">android.<wbr/>control.<wbr/>awb<wbr/>Lock<wbr/>Available</a>
+are also guaranteed to be <code>true</code> so burst capture with these two locks ON yields
+consistent image output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">YUV_REPROCESSING</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports the YUV_<wbr/>420_<wbr/>888 reprocessing use case,<wbr/> similar as
+PRIVATE_<wbr/>REPROCESSING,<wbr/> This capability requires the camera device to support the
+following:</p>
+<ul>
+<li>One input stream is supported,<wbr/> that is,<wbr/> <code><a href="#static_android.request.maxNumInputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Input<wbr/>Streams</a> == 1</code>.<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> is supported as an output/<wbr/>input format,<wbr/> that is,<wbr/>
+  YUV_<wbr/>420_<wbr/>888 is included in the lists of formats returned by
+  <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputFormats">StreamConfigurationMap#getInputFormats</a> and
+  <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputFormats">StreamConfigurationMap#getOutputFormats</a>.<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getValidOutputFormatsForInput">StreamConfigurationMap#getValidOutputFormatsForInput</a>
+  returns non-empty int[] for each supported input format returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputFormats">StreamConfigurationMap#getInputFormats</a>.<wbr/></li>
+<li>Each size returned by <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getInputSizes">get<wbr/>Input<wbr/>Sizes(YUV_<wbr/>420_<wbr/>888)</a> is also included in <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputSizes">get<wbr/>Output<wbr/>Sizes(YUV_<wbr/>420_<wbr/>888)</a></li>
+<li>Using <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> does not cause a frame rate drop
+  relative to the sensor's maximum capture rate (at that resolution).<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> will be reprocessable into both
+  <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> and <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a> formats.<wbr/></li>
+<li>The maximum available resolution for <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a> streams (both input/<wbr/>output) will match the
+  maximum available resolution of <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a> streams.<wbr/></li>
+<li>Static metadata <a href="#static_android.reprocess.maxCaptureStall">android.<wbr/>reprocess.<wbr/>max<wbr/>Capture<wbr/>Stall</a>.<wbr/></li>
+<li>Only the below controls are effective for reprocessing requests and will be present
+  in capture results.<wbr/> The reprocess requests are from the original capture results that
+  are associated with the intermediate <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a>
+  output buffers.<wbr/>  All other controls in the reprocess requests will be ignored by the
+  camera device.<wbr/><ul>
+<li>android.<wbr/>jpeg.<wbr/>*</li>
+<li><a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a></li>
+<li><a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a></li>
+<li><a href="#controls_android.reprocess.effectiveExposureFactor">android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor</a></li>
+</ul>
+</li>
+<li><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.<wbr/>noise<wbr/>Reduction.<wbr/>available<wbr/>Noise<wbr/>Reduction<wbr/>Modes</a> and
+  <a href="#static_android.edge.availableEdgeModes">android.<wbr/>edge.<wbr/>available<wbr/>Edge<wbr/>Modes</a> will both list ZERO_<wbr/>SHUTTER_<wbr/>LAG as a supported mode.<wbr/></li>
+</ul></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DEPTH_OUTPUT</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The camera device can produce depth measurements from its field of view.<wbr/></p>
+<p>This capability requires the camera device to support the following:</p>
+<ul>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#DEPTH16">ImageFormat#DEPTH16</a> is supported as an output format.<wbr/></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#DEPTH_POINT_CLOUD">Image<wbr/>Format#DEPTH_<wbr/>POINT_<wbr/>CLOUD</a> is optionally supported as an
+  output format.<wbr/></li>
+<li>This camera device,<wbr/> and all camera devices with the same <a href="#static_android.lens.facing">android.<wbr/>lens.<wbr/>facing</a>,<wbr/>
+  will list the following calibration entries in both
+  <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a> and
+  <a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html">CaptureResult</a>:<ul>
+<li><a href="#static_android.lens.poseTranslation">android.<wbr/>lens.<wbr/>pose<wbr/>Translation</a></li>
+<li><a href="#static_android.lens.poseRotation">android.<wbr/>lens.<wbr/>pose<wbr/>Rotation</a></li>
+<li><a href="#static_android.lens.intrinsicCalibration">android.<wbr/>lens.<wbr/>intrinsic<wbr/>Calibration</a></li>
+<li><a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a></li>
+</ul>
+</li>
+<li>The <a href="#static_android.depth.depthIsExclusive">android.<wbr/>depth.<wbr/>depth<wbr/>Is<wbr/>Exclusive</a> entry is listed by this device.<wbr/></li>
+<li>A LIMITED camera with only the DEPTH_<wbr/>OUTPUT capability does not have to support
+  normal YUV_<wbr/>420_<wbr/>888,<wbr/> JPEG,<wbr/> and PRIV-format outputs.<wbr/> It only has to support the DEPTH16
+  format.<wbr/></li>
+</ul>
+<p>Generally,<wbr/> depth output operates at a slower frame rate than standard color capture,<wbr/>
+so the DEPTH16 and DEPTH_<wbr/>POINT_<wbr/>CLOUD formats will commonly have a stall duration that
+should be accounted for (see
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a>).<wbr/>
+On a device that supports both depth and color-based output,<wbr/> to enable smooth preview,<wbr/>
+using a repeating burst is recommended,<wbr/> where a depth-output target is only included
+once every N frames,<wbr/> where N is the ratio between preview output rate and depth output
+rate,<wbr/> including depth stall time.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CONSTRAINED_HIGH_SPEED_VIDEO</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>The device supports constrained high speed video recording (frame rate &gt;=120fps)
+use case.<wbr/> The camera device will support high speed capture session created by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>,<wbr/> which
+only accepts high speed request lists created by
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraConstrainedHighSpeedCaptureSession.html#createHighSpeedRequestList">CameraConstrainedHighSpeedCaptureSession#createHighSpeedRequestList</a>.<wbr/></p>
+<p>A camera device can still support high speed video streaming by advertising the high speed
+FPS ranges in <a href="#static_android.control.aeAvailableTargetFpsRanges">android.<wbr/>control.<wbr/>ae<wbr/>Available<wbr/>Target<wbr/>Fps<wbr/>Ranges</a>.<wbr/> For this case,<wbr/> all normal
+capture request per frame control and synchronization requirements will apply to
+the high speed fps ranges,<wbr/> the same as all other fps ranges.<wbr/> This capability describes
+the capability of a specialized operating mode with many limitations (see below),<wbr/> which
+is only targeted at high speed video recording.<wbr/></p>
+<p>The supported high speed video sizes and fps ranges are specified in
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighSpeedVideoFpsRanges">StreamConfigurationMap#getHighSpeedVideoFpsRanges</a>.<wbr/>
+To get desired output frame rates,<wbr/> the application is only allowed to select video size
+and FPS range combinations provided by
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighSpeedVideoSizes">StreamConfigurationMap#getHighSpeedVideoSizes</a>.<wbr/>
+The fps range can be controlled via <a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a>.<wbr/></p>
+<p>In this capability,<wbr/> the camera device will override aeMode,<wbr/> awbMode,<wbr/> and afMode to
+ON,<wbr/> AUTO,<wbr/> and CONTINUOUS_<wbr/>VIDEO,<wbr/> respectively.<wbr/> All post-processing block mode
+controls will be overridden to be FAST.<wbr/> Therefore,<wbr/> no manual control of capture
+and post-processing parameters is possible.<wbr/> All other controls operate the
+same as when <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> == AUTO.<wbr/> This means that all other
+android.<wbr/>control.<wbr/>* fields continue to work,<wbr/> such as</p>
+<ul>
+<li><a href="#controls_android.control.aeTargetFpsRange">android.<wbr/>control.<wbr/>ae<wbr/>Target<wbr/>Fps<wbr/>Range</a></li>
+<li><a href="#controls_android.control.aeExposureCompensation">android.<wbr/>control.<wbr/>ae<wbr/>Exposure<wbr/>Compensation</a></li>
+<li><a href="#controls_android.control.aeLock">android.<wbr/>control.<wbr/>ae<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.awbLock">android.<wbr/>control.<wbr/>awb<wbr/>Lock</a></li>
+<li><a href="#controls_android.control.effectMode">android.<wbr/>control.<wbr/>effect<wbr/>Mode</a></li>
+<li><a href="#controls_android.control.aeRegions">android.<wbr/>control.<wbr/>ae<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afRegions">android.<wbr/>control.<wbr/>af<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.awbRegions">android.<wbr/>control.<wbr/>awb<wbr/>Regions</a></li>
+<li><a href="#controls_android.control.afTrigger">android.<wbr/>control.<wbr/>af<wbr/>Trigger</a></li>
+<li><a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a></li>
+</ul>
+<p>Outside of android.<wbr/>control.<wbr/>*,<wbr/> the following controls will work:</p>
+<ul>
+<li><a href="#controls_android.flash.mode">android.<wbr/>flash.<wbr/>mode</a> (TORCH mode only,<wbr/> automatic flash for still capture will not
+work since aeMode is ON)</li>
+<li><a href="#controls_android.lens.opticalStabilizationMode">android.<wbr/>lens.<wbr/>optical<wbr/>Stabilization<wbr/>Mode</a> (if it is supported)</li>
+<li><a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a></li>
+<li><a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> (if it is supported)</li>
+</ul>
+<p>For high speed recording use case,<wbr/> the actual maximum supported frame rate may
+be lower than what camera can output,<wbr/> depending on the destination Surfaces for
+the image data.<wbr/> For example,<wbr/> if the destination surface is from video encoder,<wbr/>
+the application need check if the video encoder is capable of supporting the
+high frame rate for a given video size,<wbr/> or it will end up with lower recording
+frame rate.<wbr/> If the destination surface is from preview window,<wbr/> the actual preview frame
+rate will be bounded by the screen refresh rate.<wbr/></p>
+<p>The camera device will only support up to 2 high speed simultaneous output surfaces
+(preview and recording surfaces)
+in this mode.<wbr/> Above controls will be effective only if all of below conditions are true:</p>
+<ul>
+<li>The application creates a camera capture session with no more than 2 surfaces via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>.<wbr/> The
+targeted surfaces must be preview surface (either from
+<a href="https://developer.android.com/reference/android/view/SurfaceView.html">SurfaceView</a> or <a href="https://developer.android.com/reference/android/graphics/SurfaceTexture.html">SurfaceTexture</a>) or
+recording surface(either from <a href="https://developer.android.com/reference/android/media/MediaRecorder.html#getSurface">MediaRecorder#getSurface</a> or
+<a href="https://developer.android.com/reference/android/media/MediaCodec.html#createInputSurface">MediaCodec#createInputSurface</a>).<wbr/></li>
+<li>The stream sizes are selected from the sizes reported by
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighSpeedVideoSizes">StreamConfigurationMap#getHighSpeedVideoSizes</a>.<wbr/></li>
+<li>The FPS ranges are selected from
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getHighSpeedVideoFpsRanges">StreamConfigurationMap#getHighSpeedVideoFpsRanges</a>.<wbr/></li>
+</ul>
+<p>When above conditions are NOT satistied,<wbr/>
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createConstrainedHighSpeedCaptureSession">CameraDevice#createConstrainedHighSpeedCaptureSession</a>
+will fail.<wbr/></p>
+<p>Switching to a FPS range that has different maximum FPS may trigger some camera device
+reconfigurations,<wbr/> which may introduce extra latency.<wbr/> It is recommended that
+the application avoids unnecessary maximum target FPS changes as much as possible
+during high speed streaming.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of capabilities that this camera device
+advertises as fully supporting.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A capability is a contract that the camera device makes in order
+to be able to satisfy one or more use cases.<wbr/></p>
+<p>Listing a capability guarantees that the whole set of features
+required to support a common use will all be available.<wbr/></p>
+<p>Using a subset of the functionality provided by an unsupported
+capability may be possible on a specific camera device implementation;
+to do this query each of <a href="#static_android.request.availableRequestKeys">android.<wbr/>request.<wbr/>available<wbr/>Request<wbr/>Keys</a>,<wbr/>
+<a href="#static_android.request.availableResultKeys">android.<wbr/>request.<wbr/>available<wbr/>Result<wbr/>Keys</a>,<wbr/>
+<a href="#static_android.request.availableCharacteristicsKeys">android.<wbr/>request.<wbr/>available<wbr/>Characteristics<wbr/>Keys</a>.<wbr/></p>
+<p>The following capabilities are guaranteed to be available on
+<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> <code>==</code> FULL devices:</p>
+<ul>
+<li>MANUAL_<wbr/>SENSOR</li>
+<li>MANUAL_<wbr/>POST_<wbr/>PROCESSING</li>
+</ul>
+<p>Other capabilities may be available on either FULL or LIMITED
+devices,<wbr/> but the application should query this key to be sure.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Additional constraint details per-capability will be available
+in the Compatibility Test Suite.<wbr/></p>
+<p>Minimum baseline requirements required for the
+BACKWARD_<wbr/>COMPATIBLE capability are not explicitly listed.<wbr/>
+Instead refer to "BC" tags and the camera CTS tests in the
+android.<wbr/>hardware.<wbr/>camera2.<wbr/>cts package.<wbr/></p>
+<p>Listed controls that can be either request or result (e.<wbr/>g.<wbr/>
+<a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a>) must be available both in the
+request and the result in order to be considered to be
+capability-compliant.<wbr/></p>
+<p>For example,<wbr/> if the HAL claims to support MANUAL control,<wbr/>
+then exposure time must be configurable via the request <em>and</em>
+the actual exposure applied must be available via
+the result.<wbr/></p>
+<p>If MANUAL_<wbr/>SENSOR is omitted,<wbr/> the HAL may choose to omit the
+<a href="#static_android.scaler.availableMinFrameDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Min<wbr/>Frame<wbr/>Durations</a> static property entirely.<wbr/></p>
+<p>For PRIVATE_<wbr/>REPROCESSING and YUV_<wbr/>REPROCESSING capabilities,<wbr/> see
+hardware/<wbr/>libhardware/<wbr/>include/<wbr/>hardware/<wbr/>camera3.<wbr/>h Section 10 for more information.<wbr/></p>
+<p>Devices that support the MANUAL_<wbr/>SENSOR capability must support the
+CAMERA3_<wbr/>TEMPLATE_<wbr/>MANUAL template defined in camera3.<wbr/>h.<wbr/></p>
+<p>Devices that support the PRIVATE_<wbr/>REPROCESSING capability or the
+YUV_<wbr/>REPROCESSING capability must support the
+CAMERA3_<wbr/>TEMPLATE_<wbr/>ZERO_<wbr/>SHUTTER_<wbr/>LAG template defined in camera3.<wbr/>h.<wbr/></p>
+<p>For DEPTH_<wbr/>OUTPUT,<wbr/> the depth-format keys
+<a href="#static_android.depth.availableDepthStreamConfigurations">android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Stream<wbr/>Configurations</a>,<wbr/>
+<a href="#static_android.depth.availableDepthMinFrameDurations">android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Min<wbr/>Frame<wbr/>Durations</a>,<wbr/>
+<a href="#static_android.depth.availableDepthStallDurations">android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Stall<wbr/>Durations</a> must be available,<wbr/> in
+addition to the other keys explicitly mentioned in the DEPTH_<wbr/>OUTPUT
+enum notes.<wbr/> The entry <a href="#static_android.depth.maxDepthSamples">android.<wbr/>depth.<wbr/>max<wbr/>Depth<wbr/>Samples</a> must be available
+if the DEPTH_<wbr/>POINT_<wbr/>CLOUD format is supported (HAL pixel format BLOB,<wbr/> dataspace
+DEPTH).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.availableRequestKeys">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>available<wbr/>Request<wbr/>Keys
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A list of all keys that the camera device has available
+to use with <a href="https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html">CaptureRequest</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Attempting to set a key into a CaptureRequest that is not
+listed here will result in an invalid request and will be rejected
+by the camera device.<wbr/></p>
+<p>This field can be used to query the feature set of a camera device
+at a more granular level than capabilities.<wbr/> This is especially
+important for optional keys that are not listed under any capability
+in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Vendor tags must not be listed here.<wbr/> Use the vendor tag metadata
+extensions C api instead (refer to camera3.<wbr/>h for more details).<wbr/></p>
+<p>Setting/<wbr/>getting vendor tags will be checked against the metadata
+vendor extensions API and not against this field.<wbr/></p>
+<p>The HAL must not consume any request tags that are not listed either
+here or in the vendor tag list.<wbr/></p>
+<p>The public camera2 API will always make the vendor tags visible
+via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.availableResultKeys">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>available<wbr/>Result<wbr/>Keys
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A list of all keys that the camera device has available
+to use with <a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html">CaptureResult</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Attempting to get a key from a CaptureResult that is not
+listed here will always return a <code>null</code> value.<wbr/> Getting a key from
+a CaptureResult that is listed here will generally never return a <code>null</code>
+value.<wbr/></p>
+<p>The following keys may return <code>null</code> unless they are enabled:</p>
+<ul>
+<li><a href="#dynamic_android.statistics.lensShadingMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map</a> (non-null iff <a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> == ON)</li>
+</ul>
+<p>(Those sometimes-null keys will nevertheless be listed here
+if they are available.<wbr/>)</p>
+<p>This field can be used to query the feature set of a camera device
+at a more granular level than capabilities.<wbr/> This is especially
+important for optional keys that are not listed under any capability
+in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Tags listed here must always have an entry in the result metadata,<wbr/>
+even if that size is 0 elements.<wbr/> Only array-type tags (e.<wbr/>g.<wbr/> lists,<wbr/>
+matrices,<wbr/> strings) are allowed to have 0 elements.<wbr/></p>
+<p>Vendor tags must not be listed here.<wbr/> Use the vendor tag metadata
+extensions C api instead (refer to camera3.<wbr/>h for more details).<wbr/></p>
+<p>Setting/<wbr/>getting vendor tags will be checked against the metadata
+vendor extensions API and not against this field.<wbr/></p>
+<p>The HAL must not produce any result tags that are not listed either
+here or in the vendor tag list.<wbr/></p>
+<p>The public camera2 API will always make the vendor tags visible via <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys">CameraCharacteristics#getAvailableCaptureResultKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.request.availableCharacteristicsKeys">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>available<wbr/>Characteristics<wbr/>Keys
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A list of all keys that the camera device has available
+to use with <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry follows the same rules as
+<a href="#static_android.request.availableResultKeys">android.<wbr/>request.<wbr/>available<wbr/>Result<wbr/>Keys</a> (except that it applies for
+CameraCharacteristics instead of CaptureResult).<wbr/> See above for more
+details.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Keys listed here must always have an entry in the static info metadata,<wbr/>
+even if that size is 0 elements.<wbr/> Only array-type tags (e.<wbr/>g.<wbr/> lists,<wbr/>
+matrices,<wbr/> strings) are allowed to have 0 elements.<wbr/></p>
+<p>Vendor tags must not be listed here.<wbr/> Use the vendor tag metadata
+extensions C api instead (refer to camera3.<wbr/>h for more details).<wbr/></p>
+<p>Setting/<wbr/>getting vendor tags will be checked against the metadata
+vendor extensions API and not against this field.<wbr/></p>
+<p>The HAL must not have any tags in its static info that are not listed
+either here or in the vendor tag list.<wbr/></p>
+<p>The public camera2 API will always make the vendor tags visible
+via <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getKeys">CameraCharacteristics#getKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.request.frameCount">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>frame<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A frame counter set by the framework.<wbr/> This value monotonically
+increases with every new result (that is,<wbr/> each new result has a unique
+frameCount value).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              count of frames
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>&gt; 0</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Reset on release()</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.request.id">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>id
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>An application-specified ID for the current
+request.<wbr/> Must be maintained unchanged in output
+frame</p>
+            </td>
+
+            <td class="entry_units">
+              arbitrary integer assigned by application
+            </td>
+
+            <td class="entry_range">
+              <p>Any int</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.request.metadataMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>request.<wbr/>metadata<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">NONE</span>
+                    <span class="entry_type_enum_notes"><p>No metadata should be produced on output,<wbr/> except
+for application-bound buffer data.<wbr/> If no
+application-bound streams exist,<wbr/> no frame should be
+placed in the output frame queue.<wbr/> If such streams
+exist,<wbr/> a frame should be placed on the output queue
+with null metadata but with the necessary output buffer
+information.<wbr/> Timestamp information should still be
+included with any output stream buffers</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FULL</span>
+                    <span class="entry_type_enum_notes"><p>All metadata should be produced.<wbr/> Statistics will
+only be produced if they are separately
+enabled</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>How much metadata to produce on
+output</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.request.outputStreams">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>request.<wbr/>output<wbr/>Streams
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Lists which camera output streams image data
+from this capture must be sent to</p>
+            </td>
+
+            <td class="entry_units">
+              List of camera stream IDs
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>List must only include streams that have been
+created</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If no output streams are listed,<wbr/> then the image
+data should simply be discarded.<wbr/> The image data must
+still be captured for metadata and statistics production,<wbr/>
+and the lens and flash must operate as requested.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.request.pipelineDepth">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>request.<wbr/>pipeline<wbr/>Depth
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Specifies the number of pipeline stages the frame went
+through from when it was exposed to when the final completed result
+was available to the framework.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&lt;= <a href="#static_android.request.pipelineMaxDepth">android.<wbr/>request.<wbr/>pipeline<wbr/>Max<wbr/>Depth</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Depending on what settings are used in the request,<wbr/> and
+what streams are configured,<wbr/> the data may undergo less processing,<wbr/>
+and some pipeline stages skipped.<wbr/></p>
+<p>See <a href="#static_android.request.pipelineMaxDepth">android.<wbr/>request.<wbr/>pipeline<wbr/>Max<wbr/>Depth</a> for more details.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value must always represent the accurate count of how many
+pipeline stages were actually used.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_scaler" class="section">scaler</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.scaler.cropRegion">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>crop<wbr/>Region
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired region of the sensor to read out for this capture.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates relative to
+          android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control can be used to implement digital zoom.<wbr/></p>
+<p>The crop region coordinate system is based off
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>,<wbr/> with <code>(0,<wbr/> 0)</code> being the
+top-left corner of the sensor active array.<wbr/></p>
+<p>Output streams use this rectangle to produce their output,<wbr/>
+cropping to a smaller region if necessary to maintain the
+stream's aspect ratio,<wbr/> then scaling the sensor input to
+match the output's configured resolution.<wbr/></p>
+<p>The crop region is applied after the RAW to other color
+space (e.<wbr/>g.<wbr/> YUV) conversion.<wbr/> Since raw streams
+(e.<wbr/>g.<wbr/> RAW16) don't have the conversion stage,<wbr/> they are not
+croppable.<wbr/> The crop region will be ignored by raw streams.<wbr/></p>
+<p>For non-raw streams,<wbr/> any additional per-stream cropping will
+be done to maximize the final pixel area of the stream.<wbr/></p>
+<p>For example,<wbr/> if the crop region is set to a 4:3 aspect
+ratio,<wbr/> then 4:3 streams will use the exact crop
+region.<wbr/> 16:9 streams will further crop vertically
+(letterbox).<wbr/></p>
+<p>Conversely,<wbr/> if the crop region is set to a 16:9,<wbr/> then 4:3
+outputs will crop horizontally (pillarbox),<wbr/> and 16:9
+streams will match exactly.<wbr/> These additional crops will
+be centered within the crop region.<wbr/></p>
+<p>The width and height of the crop region cannot
+be set to be smaller than
+<code>floor( activeArraySize.<wbr/>width /<wbr/> <a href="#static_android.scaler.availableMaxDigitalZoom">android.<wbr/>scaler.<wbr/>available<wbr/>Max<wbr/>Digital<wbr/>Zoom</a> )</code> and
+<code>floor( activeArraySize.<wbr/>height /<wbr/> <a href="#static_android.scaler.availableMaxDigitalZoom">android.<wbr/>scaler.<wbr/>available<wbr/>Max<wbr/>Digital<wbr/>Zoom</a> )</code>,<wbr/> respectively.<wbr/></p>
+<p>The camera device may adjust the crop region to account
+for rounding and other hardware requirements; the final
+crop region used will be included in the output capture
+result.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The output streams must maintain square pixels at all
+times,<wbr/> no matter what the relative aspect ratios of the
+crop region and the stream are.<wbr/>  Negative values for
+corner are allowed for raw output if full pixel array is
+larger than active pixel array.<wbr/> Width and height may be
+rounded to nearest larger supportable width,<wbr/> especially
+for raw output,<wbr/> where only a few fixed scales may be
+possible.<wbr/></p>
+<p>For a set of output streams configured,<wbr/> if the sensor output is cropped to a smaller
+size than active array size,<wbr/> the HAL need follow below cropping rules:</p>
+<ul>
+<li>
+<p>The HAL need handle the cropRegion as if the sensor crop size is the effective active
+array size.<wbr/>More specifically,<wbr/> the HAL must transform the request cropRegion from
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> to the sensor cropped pixel area size in this way:</p>
+<ol>
+<li>Translate the requested cropRegion w.<wbr/>r.<wbr/>t.,<wbr/> the left top corner of the sensor
+cropped pixel area by (tx,<wbr/> ty),<wbr/>
+where <code>tx = sensorCrop.<wbr/>top * (sensorCrop.<wbr/>height /<wbr/> activeArraySize.<wbr/>height)</code>
+and <code>tx = sensorCrop.<wbr/>left * (sensorCrop.<wbr/>width /<wbr/> activeArraySize.<wbr/>width)</code>.<wbr/> The
+(sensorCrop.<wbr/>top,<wbr/> sensorCrop.<wbr/>left) is the coordinate based off the
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></li>
+<li>Scale the width and height of requested cropRegion with scaling factor of
+sensor<wbr/>Crop.<wbr/>width/<wbr/>active<wbr/>Array<wbr/>Size.<wbr/>width and sensor<wbr/>Crop.<wbr/>height/<wbr/>active<wbr/>Array<wbr/>Size.<wbr/>height
+respectively.<wbr/>
+Once this new cropRegion is calculated,<wbr/> the HAL must use this region to crop the image
+with regard to the sensor crop size (effective active array size).<wbr/> The HAL still need
+follow the general cropping rule for this new cropRegion and effective active
+array size.<wbr/></li>
+</ol>
+</li>
+<li>
+<p>The HAL must report the cropRegion with regard to <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>
+The HAL need convert the new cropRegion generated above w.<wbr/>r.<wbr/>t.,<wbr/> full active array size.<wbr/>
+The reported cropRegion may be slightly different with the requested cropRegion since
+the HAL may adjust the crop region to account for rounding,<wbr/> conversion error,<wbr/> or other
+hardware limitations.<wbr/></p>
+</li>
+</ul>
+<p>HAL2.<wbr/>x uses only (x,<wbr/> y,<wbr/> width)</p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.scaler.availableFormats">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Formats
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [hidden as imageFormat]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">RAW16</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_value">0x20</span>
+                    <span class="entry_type_enum_notes"><p>RAW16 is a standard,<wbr/> cross-platform format for raw image
+buffers with 16-bit pixels.<wbr/></p>
+<p>Buffers of this format are typically expected to have a
+Bayer Color Filter Array (CFA) layout,<wbr/> which is given in
+<a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>.<wbr/> Sensors with
+CFAs that are not representable by a format in
+<a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a> should not
+use this format.<wbr/></p>
+<p>Buffers of this format will also follow the constraints given for
+RAW_<wbr/>OPAQUE buffers,<wbr/> but with relaxed performance constraints.<wbr/></p>
+<p>This format is intended to give users access to the full contents
+of the buffers coming directly from the image sensor prior to any
+cropping or scaling operations,<wbr/> and all coordinate systems for
+metadata used for this format are relative to the size of the
+active region of the image sensor before any geometric distortion
+correction has been applied (i.<wbr/>e.<wbr/>
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>).<wbr/> Supported
+dimensions for this format are limited to the full dimensions of
+the sensor (e.<wbr/>g.<wbr/> either <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a> or
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> will be the
+only supported output size).<wbr/></p>
+<p>See <a href="#static_android.scaler.availableInputOutputFormatsMap">android.<wbr/>scaler.<wbr/>available<wbr/>Input<wbr/>Output<wbr/>Formats<wbr/>Map</a> for
+the full set of performance guarantees.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">RAW_OPAQUE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_value">0x24</span>
+                    <span class="entry_type_enum_notes"><p>RAW_<wbr/>OPAQUE (or
+<a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_PRIVATE">RAW_<wbr/>PRIVATE</a>
+as referred in public API) is a format for raw image buffers
+coming from an image sensor.<wbr/></p>
+<p>The actual structure of buffers of this format is
+platform-specific,<wbr/> but must follow several constraints:</p>
+<ol>
+<li>No image post-processing operations may have been applied to
+buffers of this type.<wbr/> These buffers contain raw image data coming
+directly from the image sensor.<wbr/></li>
+<li>If a buffer of this format is passed to the camera device for
+reprocessing,<wbr/> the resulting images will be identical to the images
+produced if the buffer had come directly from the sensor and was
+processed with the same settings.<wbr/></li>
+</ol>
+<p>The intended use for this format is to allow access to the native
+raw format buffers coming directly from the camera sensor without
+any additional conversions or decrease in framerate.<wbr/></p>
+<p>See <a href="#static_android.scaler.availableInputOutputFormatsMap">android.<wbr/>scaler.<wbr/>available<wbr/>Input<wbr/>Output<wbr/>Formats<wbr/>Map</a> for the full set of
+performance guarantees.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">YV12</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_value">0x32315659</span>
+                    <span class="entry_type_enum_notes"><p>YCrCb 4:2:0 Planar</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">YCrCb_420_SP</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_value">0x11</span>
+                    <span class="entry_type_enum_notes"><p>NV21</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">IMPLEMENTATION_DEFINED</span>
+                    <span class="entry_type_enum_value">0x22</span>
+                    <span class="entry_type_enum_notes"><p>System internal format,<wbr/> not application-accessible</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">YCbCr_420_888</span>
+                    <span class="entry_type_enum_value">0x23</span>
+                    <span class="entry_type_enum_notes"><p>Flexible YUV420 Format</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BLOB</span>
+                    <span class="entry_type_enum_value">0x21</span>
+                    <span class="entry_type_enum_notes"><p>JPEG format</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The list of image formats that are supported by this
+camera device for output streams.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All camera devices will support JPEG and YUV_<wbr/>420_<wbr/>888 formats.<wbr/></p>
+<p>When set to YUV_<wbr/>420_<wbr/>888,<wbr/> application can access the YUV420 data directly.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>These format values are from HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>* in
+system/<wbr/>core/<wbr/>include/<wbr/>system/<wbr/>graphics.<wbr/>h.<wbr/></p>
+<p>When IMPLEMENTATION_<wbr/>DEFINED is used,<wbr/> the platform
+gralloc module will select a format based on the usage flags provided
+by the camera HAL device and the other endpoint of the stream.<wbr/> It is
+usually used by preview and recording streams,<wbr/> where the application doesn't
+need access the image data.<wbr/></p>
+<p>YCb<wbr/>Cr_<wbr/>420_<wbr/>888 format must be supported by the HAL.<wbr/> When an image stream
+needs CPU/<wbr/>application direct access,<wbr/> this format will be used.<wbr/></p>
+<p>The BLOB format must be supported by the HAL.<wbr/> This is used for the JPEG stream.<wbr/></p>
+<p>A RAW_<wbr/>OPAQUE buffer should contain only pixel data.<wbr/> It is strongly
+recommended that any information used by the camera device when
+processing images is fully expressed by the result metadata
+for that image buffer.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableJpegMinDurations">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Jpeg<wbr/>Min<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The minimum frame duration that is supported
+for each resolution in <a href="#static_android.scaler.availableJpegSizes">android.<wbr/>scaler.<wbr/>available<wbr/>Jpeg<wbr/>Sizes</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>TODO: Remove property.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This corresponds to the minimum steady-state frame duration when only
+that JPEG stream is active and captured in a burst,<wbr/> with all
+processing (typically in android.<wbr/>*.<wbr/>mode) set to FAST.<wbr/></p>
+<p>When multiple streams are configured,<wbr/> the minimum
+frame duration will be &gt;= max(individual stream min
+durations)</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableJpegSizes">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Jpeg<wbr/>Sizes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [hidden as size]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The JPEG resolutions that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+              <p>TODO: Remove property.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The resolutions are listed as <code>(width,<wbr/> height)</code> pairs.<wbr/> All camera devices will support
+sensor maximum resolution (defined by <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must include sensor maximum resolution
+(defined by <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>),<wbr/>
+and should include half/<wbr/>quarter of sensor maximum resolution.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableMaxDigitalZoom">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Max<wbr/>Digital<wbr/>Zoom
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum ratio between both active area width
+and crop region width,<wbr/> and active area height and
+crop region height,<wbr/> for <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Zoom scale factor
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;=1</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This represents the maximum amount of zooming possible by
+the camera device,<wbr/> or equivalently,<wbr/> the minimum cropping
+window size.<wbr/></p>
+<p>Crop regions that have a width or height that is smaller
+than this ratio allows will be rounded up to the minimum
+allowed size by the camera device.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableProcessedMinDurations">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Processed<wbr/>Min<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>For each available processed output size (defined in
+<a href="#static_android.scaler.availableProcessedSizes">android.<wbr/>scaler.<wbr/>available<wbr/>Processed<wbr/>Sizes</a>),<wbr/> this property lists the
+minimum supportable frame duration for that size.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This should correspond to the frame duration when only that processed
+stream is active,<wbr/> with all processing (typically in android.<wbr/>*.<wbr/>mode)
+set to FAST.<wbr/></p>
+<p>When multiple streams are configured,<wbr/> the minimum frame duration will
+be &gt;= max(individual stream min durations).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableProcessedSizes">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Processed<wbr/>Sizes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [hidden as size]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The resolutions available for use with
+processed output streams,<wbr/> such as YV12,<wbr/> NV12,<wbr/> and
+platform opaque YUV/<wbr/>RGB streams to the GPU or video
+encoders.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The resolutions are listed as <code>(width,<wbr/> height)</code> pairs.<wbr/></p>
+<p>For a given use case,<wbr/> the actual maximum supported resolution
+may be lower than what is listed here,<wbr/> depending on the destination
+Surface for the image data.<wbr/> For example,<wbr/> for recording video,<wbr/>
+the video encoder chosen may have a maximum size limit (e.<wbr/>g.<wbr/> 1080p)
+smaller than what the camera (e.<wbr/>g.<wbr/> maximum resolution is 3264x2448)
+can provide.<wbr/></p>
+<p>Please reference the documentation for the image data destination to
+check if it limits the maximum size for image data.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For FULL capability devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL</code>),<wbr/>
+the HAL must include all JPEG sizes listed in <a href="#static_android.scaler.availableJpegSizes">android.<wbr/>scaler.<wbr/>available<wbr/>Jpeg<wbr/>Sizes</a>
+and each below resolution if it is smaller than or equal to the sensor
+maximum resolution (if they are not listed in JPEG sizes already):</p>
+<ul>
+<li>240p (320 x 240)</li>
+<li>480p (640 x 480)</li>
+<li>720p (1280 x 720)</li>
+<li>1080p (1920 x 1080)</li>
+</ul>
+<p>For LIMITED capability devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == LIMITED</code>),<wbr/>
+the HAL only has to list up to the maximum video size supported by the devices.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableRawMinDurations">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Raw<wbr/>Min<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>For each available raw output size (defined in
+<a href="#static_android.scaler.availableRawSizes">android.<wbr/>scaler.<wbr/>available<wbr/>Raw<wbr/>Sizes</a>),<wbr/> this property lists the minimum
+supportable frame duration for that size.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Should correspond to the frame duration when only the raw stream is
+active.<wbr/></p>
+<p>When multiple streams are configured,<wbr/> the minimum
+frame duration will be &gt;= max(individual stream min
+durations)</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableRawSizes">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="1">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Raw<wbr/>Sizes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [system as size]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The resolutions available for use with raw
+sensor output streams,<wbr/> listed as width,<wbr/>
+height</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableInputOutputFormatsMap">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Input<wbr/>Output<wbr/>Formats<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [hidden as reprocessFormatsMap]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The mapping of image formats that are supported by this
+camera device for input streams,<wbr/> to their corresponding output formats.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All camera devices with at least 1
+<a href="#static_android.request.maxNumInputStreams">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Input<wbr/>Streams</a> will have at least one
+available input format.<wbr/></p>
+<p>The camera device will support the following map of formats,<wbr/>
+if its dependent capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>) is supported:</p>
+<table>
+<thead>
+<tr>
+<th align="left">Input Format</th>
+<th align="left">Output Format</th>
+<th align="left">Capability</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a></td>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="left">PRIVATE_<wbr/>REPROCESSING</td>
+</tr>
+<tr>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a></td>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="left">PRIVATE_<wbr/>REPROCESSING</td>
+</tr>
+<tr>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="left">YUV_<wbr/>REPROCESSING</td>
+</tr>
+<tr>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="left"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="left">YUV_<wbr/>REPROCESSING</td>
+</tr>
+</tbody>
+</table>
+<p>PRIVATE refers to a device-internal format that is not directly application-visible.<wbr/>  A
+PRIVATE input surface can be acquired by <a href="https://developer.android.com/reference/android/media/ImageReader.html#newInstance">ImageReader#newInstance</a>
+with <a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a> as the format.<wbr/></p>
+<p>For a PRIVATE_<wbr/>REPROCESSING-capable camera device,<wbr/> using the PRIVATE format as either input
+or output will never hurt maximum frame rate (i.<wbr/>e.<wbr/>  <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">getOutputStallDuration(ImageFormat.<wbr/>PRIVATE,<wbr/> size)</a> is always 0),<wbr/></p>
+<p>Attempting to configure an input stream with output streams not
+listed as available in this map is not valid.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For the formats,<wbr/> see <code>system/<wbr/>core/<wbr/>include/<wbr/>system/<wbr/>graphics.<wbr/>h</code> for a definition
+of the image format enumerations.<wbr/> The PRIVATE format refers to the
+HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>IMPLEMENTATION_<wbr/>DEFINED format.<wbr/> The HAL could determine
+the actual format by using the gralloc usage flags.<wbr/>
+For ZSL use case in particular,<wbr/> the HAL could choose appropriate format (partially
+processed YUV or RAW based format) by checking the format and GRALLOC_<wbr/>USAGE_<wbr/>HW_<wbr/>CAMERA_<wbr/>ZSL.<wbr/>
+See camera3.<wbr/>h for more details.<wbr/></p>
+<p>This value is encoded as a variable-size array-of-arrays.<wbr/>
+The inner array always contains <code>[format,<wbr/> length,<wbr/> ...<wbr/>]</code> where
+<code>...<wbr/></code> has <code>length</code> elements.<wbr/> An inner array is followed by another
+inner array if the total metadata entry size hasn't yet been exceeded.<wbr/></p>
+<p>A code sample to read/<wbr/>write this encoding (with a device that
+supports reprocessing IMPLEMENTATION_<wbr/>DEFINED to YUV_<wbr/>420_<wbr/>888,<wbr/> and JPEG,<wbr/>
+and reprocessing YUV_<wbr/>420_<wbr/>888 to YUV_<wbr/>420_<wbr/>888 and JPEG):</p>
+<pre><code>//<wbr/> reading
+int32_<wbr/>t* contents = &amp;entry.<wbr/>i32[0];
+for (size_<wbr/>t i = 0; i &lt; entry.<wbr/>count; ) {
+    int32_<wbr/>t format = contents[i++];
+    int32_<wbr/>t length = contents[i++];
+    int32_<wbr/>t output_<wbr/>formats[length];
+    memcpy(&amp;output_<wbr/>formats[0],<wbr/> &amp;contents[i],<wbr/>
+           length * sizeof(int32_<wbr/>t));
+    i += length;
+}
+
+//<wbr/> writing (static example,<wbr/> PRIVATE_<wbr/>REPROCESSING + YUV_<wbr/>REPROCESSING)
+int32_<wbr/>t[] contents = {
+  IMPLEMENTATION_<wbr/>DEFINED,<wbr/> 2,<wbr/> YUV_<wbr/>420_<wbr/>888,<wbr/> BLOB,<wbr/>
+  YUV_<wbr/>420_<wbr/>888,<wbr/> 2,<wbr/> YUV_<wbr/>420_<wbr/>888,<wbr/> BLOB,<wbr/>
+};
+update_<wbr/>camera_<wbr/>metadata_<wbr/>entry(metadata,<wbr/> index,<wbr/> &amp;contents[0],<wbr/>
+      sizeof(contents)/<wbr/>sizeof(contents[0]),<wbr/> &amp;updated_<wbr/>entry);
+</code></pre>
+<p>If the HAL claims to support any of the capabilities listed in the
+above details,<wbr/> then it must also support all the input-output
+combinations listed for that capability.<wbr/> It can optionally support
+additional formats if it so chooses.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableStreamConfigurations">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 4
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OUTPUT</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">INPUT</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The available stream configurations that this
+camera device supports
+(i.<wbr/>e.<wbr/> format,<wbr/> width,<wbr/> height,<wbr/> output/<wbr/>input stream).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The configurations are listed as <code>(format,<wbr/> width,<wbr/> height,<wbr/> input?)</code>
+tuples.<wbr/></p>
+<p>For a given use case,<wbr/> the actual maximum supported resolution
+may be lower than what is listed here,<wbr/> depending on the destination
+Surface for the image data.<wbr/> For example,<wbr/> for recording video,<wbr/>
+the video encoder chosen may have a maximum size limit (e.<wbr/>g.<wbr/> 1080p)
+smaller than what the camera (e.<wbr/>g.<wbr/> maximum resolution is 3264x2448)
+can provide.<wbr/></p>
+<p>Please reference the documentation for the image data destination to
+check if it limits the maximum size for image data.<wbr/></p>
+<p>Not all output formats may be supported in a configuration with
+an input stream of a particular format.<wbr/> For more details,<wbr/> see
+<a href="#static_android.scaler.availableInputOutputFormatsMap">android.<wbr/>scaler.<wbr/>available<wbr/>Input<wbr/>Output<wbr/>Formats<wbr/>Map</a>.<wbr/></p>
+<p>The following table describes the minimum required output stream
+configurations based on the hardware level
+(<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a>):</p>
+<table>
+<thead>
+<tr>
+<th align="center">Format</th>
+<th align="center">Size</th>
+<th align="center">Hardware Level</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center">JPEG</td>
+<td align="center"><a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a></td>
+<td align="center">Any</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center">JPEG</td>
+<td align="center">1920x1080 (1080p)</td>
+<td align="center">Any</td>
+<td align="center">if 1080p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center">JPEG</td>
+<td align="center">1280x720 (720)</td>
+<td align="center">Any</td>
+<td align="center">if 720p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center">JPEG</td>
+<td align="center">640x480 (480p)</td>
+<td align="center">Any</td>
+<td align="center">if 480p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center">JPEG</td>
+<td align="center">320x240 (240p)</td>
+<td align="center">Any</td>
+<td align="center">if 240p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center">YUV_<wbr/>420_<wbr/>888</td>
+<td align="center">all output sizes available for JPEG</td>
+<td align="center">FULL</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center">YUV_<wbr/>420_<wbr/>888</td>
+<td align="center">all output sizes available for JPEG,<wbr/> up to the maximum video size</td>
+<td align="center">LIMITED</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center">IMPLEMENTATION_<wbr/>DEFINED</td>
+<td align="center">same as YUV_<wbr/>420_<wbr/>888</td>
+<td align="center">Any</td>
+<td align="center"></td>
+</tr>
+</tbody>
+</table>
+<p>Refer to <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> for additional
+mandatory stream configurations on a per-capability basis.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>It is recommended (but not mandatory) to also include half/<wbr/>quarter
+of sensor maximum resolution for JPEG formats (regardless of hardware
+level).<wbr/></p>
+<p>(The following is a rewording of the above required table):</p>
+<p>For JPEG format,<wbr/> the sizes may be restricted by below conditions:</p>
+<ul>
+<li>The HAL may choose the aspect ratio of each Jpeg size to be one of well known ones
+(e.<wbr/>g.<wbr/> 4:3,<wbr/> 16:9,<wbr/> 3:2 etc.<wbr/>).<wbr/> If the sensor maximum resolution
+(defined by <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>) has an aspect ratio other than these,<wbr/>
+it does not have to be included in the supported JPEG sizes.<wbr/></li>
+<li>Some hardware JPEG encoders may have pixel boundary alignment requirements,<wbr/> such as
+the dimensions being a multiple of 16.<wbr/></li>
+</ul>
+<p>Therefore,<wbr/> the maximum JPEG size may be smaller than sensor maximum resolution.<wbr/>
+However,<wbr/> the largest JPEG size must be as close as possible to the sensor maximum
+resolution given above constraints.<wbr/> It is required that after aspect ratio adjustments,<wbr/>
+additional size reduction due to other issues must be less than 3% in area.<wbr/> For example,<wbr/>
+if the sensor maximum resolution is 3280x2464,<wbr/> if the maximum JPEG size has aspect
+ratio 4:3,<wbr/> the JPEG encoder alignment requirement is 16,<wbr/> the maximum JPEG size will be
+3264x2448.<wbr/></p>
+<p>For FULL capability devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL</code>),<wbr/>
+the HAL must include all YUV_<wbr/>420_<wbr/>888 sizes that have JPEG sizes listed
+here as output streams.<wbr/></p>
+<p>It must also include each below resolution if it is smaller than or
+equal to the sensor maximum resolution (for both YUV_<wbr/>420_<wbr/>888 and JPEG
+formats),<wbr/> as output streams:</p>
+<ul>
+<li>240p (320 x 240)</li>
+<li>480p (640 x 480)</li>
+<li>720p (1280 x 720)</li>
+<li>1080p (1920 x 1080)</li>
+</ul>
+<p>For LIMITED capability devices
+(<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == LIMITED</code>),<wbr/>
+the HAL only has to list up to the maximum video size
+supported by the device.<wbr/></p>
+<p>Regardless of hardware level,<wbr/> every output resolution available for
+YUV_<wbr/>420_<wbr/>888 must also be available for IMPLEMENTATION_<wbr/>DEFINED.<wbr/></p>
+<p>This supercedes the following fields,<wbr/> which are now deprecated:</p>
+<ul>
+<li>availableFormats</li>
+<li>available[Processed,<wbr/>Raw,<wbr/>Jpeg]Sizes</li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableMinFrameDurations">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Min<wbr/>Frame<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This lists the minimum frame duration for each
+format/<wbr/>size combination.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              (format,<wbr/> width,<wbr/> height,<wbr/> ns) x n
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This should correspond to the frame duration when only that
+stream is active,<wbr/> with all processing (typically in android.<wbr/>*.<wbr/>mode)
+set to either OFF or FAST.<wbr/></p>
+<p>When multiple streams are used in a request,<wbr/> the minimum frame
+duration will be max(individual stream min durations).<wbr/></p>
+<p>The minimum frame duration of a stream (of a particular format,<wbr/> size)
+is the same regardless of whether the stream is input or output.<wbr/></p>
+<p>See <a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> and
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a> for more details about
+calculating the max frame rate.<wbr/></p>
+<p>(Keep in sync with
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>)</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.availableStallDurations">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This lists the maximum stall duration for each
+output format/<wbr/>size combination.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              (format,<wbr/> width,<wbr/> height,<wbr/> ns) x n
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A stall duration is how much extra time would get added
+to the normal minimum frame duration for a repeating request
+that has streams with non-zero stall.<wbr/></p>
+<p>For example,<wbr/> consider JPEG captures which have the following
+characteristics:</p>
+<ul>
+<li>JPEG streams act like processed YUV streams in requests for which
+they are not included; in requests in which they are directly
+referenced,<wbr/> they act as JPEG streams.<wbr/> This is because supporting a
+JPEG stream requires the underlying YUV data to always be ready for
+use by a JPEG encoder,<wbr/> but the encoder will only be used (and impact
+frame duration) on requests that actually reference a JPEG stream.<wbr/></li>
+<li>The JPEG processor can run concurrently to the rest of the camera
+pipeline,<wbr/> but cannot process more than 1 capture at a time.<wbr/></li>
+</ul>
+<p>In other words,<wbr/> using a repeating YUV request would result
+in a steady frame rate (let's say it's 30 FPS).<wbr/> If a single
+JPEG request is submitted periodically,<wbr/> the frame rate will stay
+at 30 FPS (as long as we wait for the previous JPEG to return each
+time).<wbr/> If we try to submit a repeating YUV + JPEG request,<wbr/> then
+the frame rate will drop from 30 FPS.<wbr/></p>
+<p>In general,<wbr/> submitting a new request with a non-0 stall time
+stream will <em>not</em> cause a frame rate drop unless there are still
+outstanding buffers for that stream from previous requests.<wbr/></p>
+<p>Submitting a repeating request with streams (call this <code>S</code>)
+is the same as setting the minimum frame duration from
+the normal minimum frame duration corresponding to <code>S</code>,<wbr/> added with
+the maximum stall duration for <code>S</code>.<wbr/></p>
+<p>If interleaving requests with and without a stall duration,<wbr/>
+a request will stall by the maximum of the remaining times
+for each can-stall stream with outstanding buffers.<wbr/></p>
+<p>This means that a stalling request will not have an exposure start
+until the stall has completed.<wbr/></p>
+<p>This should correspond to the stall duration when only that stream is
+active,<wbr/> with all processing (typically in android.<wbr/>*.<wbr/>mode) set to FAST
+or OFF.<wbr/> Setting any of the processing modes to HIGH_<wbr/>QUALITY
+effectively results in an indeterminate stall duration for all
+streams in a request (the regular stall calculation rules are
+ignored).<wbr/></p>
+<p>The following formats may always have a stall duration:</p>
+<ul>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW_SENSOR">ImageFormat#RAW_<wbr/>SENSOR</a></li>
+</ul>
+<p>The following formats will never have a stall duration:</p>
+<ul>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></li>
+<li><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#RAW10">ImageFormat#RAW10</a></li>
+</ul>
+<p>All other formats may or may not have an allowed stall duration on
+a per-capability basis; refer to <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>
+for more details.<wbr/></p>
+<p>See <a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> for more information about
+calculating the max frame rate (absent stalls).<wbr/></p>
+<p>(Keep up to date with
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a> )</p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If possible,<wbr/> it is recommended that all non-JPEG formats
+(such as RAW16) should not have a stall duration.<wbr/> RAW10,<wbr/> RAW12,<wbr/> RAW_<wbr/>OPAQUE
+and IMPLEMENTATION_<wbr/>DEFINED must not have stall durations.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.streamConfigurationMap">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public as streamConfigurationMap]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The available stream configurations that this
+camera device supports; also includes the minimum frame durations
+and the stall durations for each format/<wbr/>size combination.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All camera devices will support sensor maximum resolution (defined by
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>) for the JPEG format.<wbr/></p>
+<p>For a given use case,<wbr/> the actual maximum supported resolution
+may be lower than what is listed here,<wbr/> depending on the destination
+Surface for the image data.<wbr/> For example,<wbr/> for recording video,<wbr/>
+the video encoder chosen may have a maximum size limit (e.<wbr/>g.<wbr/> 1080p)
+smaller than what the camera (e.<wbr/>g.<wbr/> maximum resolution is 3264x2448)
+can provide.<wbr/></p>
+<p>Please reference the documentation for the image data destination to
+check if it limits the maximum size for image data.<wbr/></p>
+<p>The following table describes the minimum required output stream
+configurations based on the hardware level
+(<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a>):</p>
+<table>
+<thead>
+<tr>
+<th align="center">Format</th>
+<th align="center">Size</th>
+<th align="center">Hardware Level</th>
+<th align="center">Notes</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="center"><a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> (*1)</td>
+<td align="center">Any</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="center">1920x1080 (1080p)</td>
+<td align="center">Any</td>
+<td align="center">if 1080p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="center">1280x720 (720p)</td>
+<td align="center">Any</td>
+<td align="center">if 720p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="center">640x480 (480p)</td>
+<td align="center">Any</td>
+<td align="center">if 480p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#JPEG">ImageFormat#JPEG</a></td>
+<td align="center">320x240 (240p)</td>
+<td align="center">Any</td>
+<td align="center">if 240p &lt;= activeArraySize</td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="center">all output sizes available for JPEG</td>
+<td align="center">FULL</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#YUV_420_888">Image<wbr/>Format#YUV_<wbr/>420_<wbr/>888</a></td>
+<td align="center">all output sizes available for JPEG,<wbr/> up to the maximum video size</td>
+<td align="center">LIMITED</td>
+<td align="center"></td>
+</tr>
+<tr>
+<td align="center"><a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#PRIVATE">ImageFormat#PRIVATE</a></td>
+<td align="center">same as YUV_<wbr/>420_<wbr/>888</td>
+<td align="center">Any</td>
+<td align="center"></td>
+</tr>
+</tbody>
+</table>
+<p>Refer to <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> and <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">CameraDevice#createCaptureSession</a> for additional mandatory
+stream configurations on a per-capability basis.<wbr/></p>
+<p>*1: For JPEG format,<wbr/> the sizes may be restricted by below conditions:</p>
+<ul>
+<li>The HAL may choose the aspect ratio of each Jpeg size to be one of well known ones
+(e.<wbr/>g.<wbr/> 4:3,<wbr/> 16:9,<wbr/> 3:2 etc.<wbr/>).<wbr/> If the sensor maximum resolution
+(defined by <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>) has an aspect ratio other than these,<wbr/>
+it does not have to be included in the supported JPEG sizes.<wbr/></li>
+<li>Some hardware JPEG encoders may have pixel boundary alignment requirements,<wbr/> such as
+the dimensions being a multiple of 16.<wbr/>
+Therefore,<wbr/> the maximum JPEG size may be smaller than sensor maximum resolution.<wbr/>
+However,<wbr/> the largest JPEG size will be as close as possible to the sensor maximum
+resolution given above constraints.<wbr/> It is required that after aspect ratio adjustments,<wbr/>
+additional size reduction due to other issues must be less than 3% in area.<wbr/> For example,<wbr/>
+if the sensor maximum resolution is 3280x2464,<wbr/> if the maximum JPEG size has aspect
+ratio 4:3,<wbr/> and the JPEG encoder alignment requirement is 16,<wbr/> the maximum JPEG size will be
+3264x2448.<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Do not set this property directly
+(it is synthetic and will not be available at the HAL layer);
+set the <a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> instead.<wbr/></p>
+<p>Not all output formats may be supported in a configuration with
+an input stream of a particular format.<wbr/> For more details,<wbr/> see
+<a href="#static_android.scaler.availableInputOutputFormatsMap">android.<wbr/>scaler.<wbr/>available<wbr/>Input<wbr/>Output<wbr/>Formats<wbr/>Map</a>.<wbr/></p>
+<p>It is recommended (but not mandatory) to also include half/<wbr/>quarter
+of sensor maximum resolution for JPEG formats (regardless of hardware
+level).<wbr/></p>
+<p>(The following is a rewording of the above required table):</p>
+<p>The HAL must include sensor maximum resolution (defined by
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>).<wbr/></p>
+<p>For FULL capability devices (<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL</code>),<wbr/>
+the HAL must include all YUV_<wbr/>420_<wbr/>888 sizes that have JPEG sizes listed
+here as output streams.<wbr/></p>
+<p>It must also include each below resolution if it is smaller than or
+equal to the sensor maximum resolution (for both YUV_<wbr/>420_<wbr/>888 and JPEG
+formats),<wbr/> as output streams:</p>
+<ul>
+<li>240p (320 x 240)</li>
+<li>480p (640 x 480)</li>
+<li>720p (1280 x 720)</li>
+<li>1080p (1920 x 1080)</li>
+</ul>
+<p>For LIMITED capability devices
+(<code><a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == LIMITED</code>),<wbr/>
+the HAL only has to list up to the maximum video size
+supported by the device.<wbr/></p>
+<p>Regardless of hardware level,<wbr/> every output resolution available for
+YUV_<wbr/>420_<wbr/>888 must also be available for IMPLEMENTATION_<wbr/>DEFINED.<wbr/></p>
+<p>This supercedes the following fields,<wbr/> which are now deprecated:</p>
+<ul>
+<li>availableFormats</li>
+<li>available[Processed,<wbr/>Raw,<wbr/>Jpeg]Sizes</li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.scaler.croppingType">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>scaler.<wbr/>cropping<wbr/>Type
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CENTER_ONLY</span>
+                    <span class="entry_type_enum_notes"><p>The camera device only supports centered crop regions.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FREEFORM</span>
+                    <span class="entry_type_enum_notes"><p>The camera device supports arbitrarily chosen crop regions.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The crop type that this camera device supports.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When passing a non-centered crop region (<a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a>) to a camera
+device that only supports CENTER_<wbr/>ONLY cropping,<wbr/> the camera device will move the
+crop region to the center of the sensor active array (<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>)
+and keep the crop region width and height unchanged.<wbr/> The camera device will return the
+final used crop region in metadata result <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a>.<wbr/></p>
+<p>Camera devices that support FREEFORM cropping will support any crop region that
+is inside of the active array.<wbr/> The camera device will apply the same crop region and
+return the final used crop region in capture result metadata <a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a>.<wbr/></p>
+<p>LEGACY capability devices will only support CENTER_<wbr/>ONLY cropping.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.scaler.cropRegion">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>scaler.<wbr/>crop<wbr/>Region
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The desired region of the sensor to read out for this capture.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates relative to
+          android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This control can be used to implement digital zoom.<wbr/></p>
+<p>The crop region coordinate system is based off
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>,<wbr/> with <code>(0,<wbr/> 0)</code> being the
+top-left corner of the sensor active array.<wbr/></p>
+<p>Output streams use this rectangle to produce their output,<wbr/>
+cropping to a smaller region if necessary to maintain the
+stream's aspect ratio,<wbr/> then scaling the sensor input to
+match the output's configured resolution.<wbr/></p>
+<p>The crop region is applied after the RAW to other color
+space (e.<wbr/>g.<wbr/> YUV) conversion.<wbr/> Since raw streams
+(e.<wbr/>g.<wbr/> RAW16) don't have the conversion stage,<wbr/> they are not
+croppable.<wbr/> The crop region will be ignored by raw streams.<wbr/></p>
+<p>For non-raw streams,<wbr/> any additional per-stream cropping will
+be done to maximize the final pixel area of the stream.<wbr/></p>
+<p>For example,<wbr/> if the crop region is set to a 4:3 aspect
+ratio,<wbr/> then 4:3 streams will use the exact crop
+region.<wbr/> 16:9 streams will further crop vertically
+(letterbox).<wbr/></p>
+<p>Conversely,<wbr/> if the crop region is set to a 16:9,<wbr/> then 4:3
+outputs will crop horizontally (pillarbox),<wbr/> and 16:9
+streams will match exactly.<wbr/> These additional crops will
+be centered within the crop region.<wbr/></p>
+<p>The width and height of the crop region cannot
+be set to be smaller than
+<code>floor( activeArraySize.<wbr/>width /<wbr/> <a href="#static_android.scaler.availableMaxDigitalZoom">android.<wbr/>scaler.<wbr/>available<wbr/>Max<wbr/>Digital<wbr/>Zoom</a> )</code> and
+<code>floor( activeArraySize.<wbr/>height /<wbr/> <a href="#static_android.scaler.availableMaxDigitalZoom">android.<wbr/>scaler.<wbr/>available<wbr/>Max<wbr/>Digital<wbr/>Zoom</a> )</code>,<wbr/> respectively.<wbr/></p>
+<p>The camera device may adjust the crop region to account
+for rounding and other hardware requirements; the final
+crop region used will be included in the output capture
+result.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The output streams must maintain square pixels at all
+times,<wbr/> no matter what the relative aspect ratios of the
+crop region and the stream are.<wbr/>  Negative values for
+corner are allowed for raw output if full pixel array is
+larger than active pixel array.<wbr/> Width and height may be
+rounded to nearest larger supportable width,<wbr/> especially
+for raw output,<wbr/> where only a few fixed scales may be
+possible.<wbr/></p>
+<p>For a set of output streams configured,<wbr/> if the sensor output is cropped to a smaller
+size than active array size,<wbr/> the HAL need follow below cropping rules:</p>
+<ul>
+<li>
+<p>The HAL need handle the cropRegion as if the sensor crop size is the effective active
+array size.<wbr/>More specifically,<wbr/> the HAL must transform the request cropRegion from
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> to the sensor cropped pixel area size in this way:</p>
+<ol>
+<li>Translate the requested cropRegion w.<wbr/>r.<wbr/>t.,<wbr/> the left top corner of the sensor
+cropped pixel area by (tx,<wbr/> ty),<wbr/>
+where <code>tx = sensorCrop.<wbr/>top * (sensorCrop.<wbr/>height /<wbr/> activeArraySize.<wbr/>height)</code>
+and <code>tx = sensorCrop.<wbr/>left * (sensorCrop.<wbr/>width /<wbr/> activeArraySize.<wbr/>width)</code>.<wbr/> The
+(sensorCrop.<wbr/>top,<wbr/> sensorCrop.<wbr/>left) is the coordinate based off the
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></li>
+<li>Scale the width and height of requested cropRegion with scaling factor of
+sensor<wbr/>Crop.<wbr/>width/<wbr/>active<wbr/>Array<wbr/>Size.<wbr/>width and sensor<wbr/>Crop.<wbr/>height/<wbr/>active<wbr/>Array<wbr/>Size.<wbr/>height
+respectively.<wbr/>
+Once this new cropRegion is calculated,<wbr/> the HAL must use this region to crop the image
+with regard to the sensor crop size (effective active array size).<wbr/> The HAL still need
+follow the general cropping rule for this new cropRegion and effective active
+array size.<wbr/></li>
+</ol>
+</li>
+<li>
+<p>The HAL must report the cropRegion with regard to <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/>
+The HAL need convert the new cropRegion generated above w.<wbr/>r.<wbr/>t.,<wbr/> full active array size.<wbr/>
+The reported cropRegion may be slightly different with the requested cropRegion since
+the HAL may adjust the crop region to account for rounding,<wbr/> conversion error,<wbr/> or other
+hardware limitations.<wbr/></p>
+</li>
+</ul>
+<p>HAL2.<wbr/>x uses only (x,<wbr/> y,<wbr/> width)</p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_sensor" class="section">sensor</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.sensor.exposureTime">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>exposure<wbr/>Time
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Duration each pixel is exposed to
+light.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the sensor can't expose this exact duration,<wbr/> it will shorten the
+duration exposed to the nearest possible value (rather than expose longer).<wbr/>
+The final exposure time used will be available in the output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.sensor.frameDuration">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>frame<wbr/>Duration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Duration from start of frame exposure to
+start of next frame exposure.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>See <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a>,<wbr/>
+<a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a>.<wbr/> The duration
+is capped to <code>max(duration,<wbr/> exposureTime + overhead)</code>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The maximum frame rate that can be supported by a camera subsystem is
+a function of many factors:</p>
+<ul>
+<li>Requested resolutions of output image streams</li>
+<li>Availability of binning /<wbr/> skipping modes on the imager</li>
+<li>The bandwidth of the imager interface</li>
+<li>The bandwidth of the various ISP processing blocks</li>
+</ul>
+<p>Since these factors can vary greatly between different ISPs and
+sensors,<wbr/> the camera abstraction tries to represent the bandwidth
+restrictions with as simple a model as possible.<wbr/></p>
+<p>The model presented has the following characteristics:</p>
+<ul>
+<li>The image sensor is always configured to output the smallest
+resolution possible given the application's requested output stream
+sizes.<wbr/>  The smallest resolution is defined as being at least as large
+as the largest requested output stream size; the camera pipeline must
+never digitally upsample sensor data when the crop region covers the
+whole sensor.<wbr/> In general,<wbr/> this means that if only small output stream
+resolutions are configured,<wbr/> the sensor can provide a higher frame
+rate.<wbr/></li>
+<li>Since any request may use any or all the currently configured
+output streams,<wbr/> the sensor and ISP must be configured to support
+scaling a single capture to all the streams at the same time.<wbr/>  This
+means the camera pipeline must be ready to produce the largest
+requested output size without any delay.<wbr/>  Therefore,<wbr/> the overall
+frame rate of a given configured stream set is governed only by the
+largest requested stream resolution.<wbr/></li>
+<li>Using more than one output stream in a request does not affect the
+frame duration.<wbr/></li>
+<li>Certain format-streams may need to do additional background processing
+before data is consumed/<wbr/>produced by that stream.<wbr/> These processors
+can run concurrently to the rest of the camera pipeline,<wbr/> but
+cannot process more than 1 capture at a time.<wbr/></li>
+</ul>
+<p>The necessary information for the application,<wbr/> given the model above,<wbr/>
+is provided via the <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> field using
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>.<wbr/>
+These are used to determine the maximum frame rate /<wbr/> minimum frame
+duration that is possible for a given stream configuration.<wbr/></p>
+<p>Specifically,<wbr/> the application can use the following rules to
+determine the minimum frame duration it can request from the camera
+device:</p>
+<ol>
+<li>Let the set of currently configured input/<wbr/>output streams
+be called <code>S</code>.<wbr/></li>
+<li>Find the minimum frame durations for each stream in <code>S</code>,<wbr/> by looking
+it up in <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> using <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>
+(with its respective size/<wbr/>format).<wbr/> Let this set of frame durations be
+called <code>F</code>.<wbr/></li>
+<li>For any given request <code>R</code>,<wbr/> the minimum frame duration allowed
+for <code>R</code> is the maximum out of all values in <code>F</code>.<wbr/> Let the streams
+used in <code>R</code> be called <code>S_<wbr/>r</code>.<wbr/></li>
+</ol>
+<p>If none of the streams in <code>S_<wbr/>r</code> have a stall time (listed in <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a>
+using its respective size/<wbr/>format),<wbr/> then the frame duration in <code>F</code>
+determines the steady state frame rate that the application will get
+if it uses <code>R</code> as a repeating request.<wbr/> Let this special kind of
+request be called <code>Rsimple</code>.<wbr/></p>
+<p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
+by a single capture of a new request <code>Rstall</code> (which has at least
+one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
+same minimum frame duration this will not cause a frame rate loss
+if all buffers from the previous <code>Rstall</code> have already been
+delivered.<wbr/></p>
+<p>For more details about stalling,<wbr/> see
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a>.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For more details about stalling,<wbr/> see
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.sensor.sensitivity">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of gain applied to sensor data
+before processing.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The sensitivity is the standard ISO sensitivity value,<wbr/>
+as defined in ISO 12232:2006.<wbr/></p>
+<p>The sensitivity must be within <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a>,<wbr/> and
+if if it less than <a href="#static_android.sensor.maxAnalogSensitivity">android.<wbr/>sensor.<wbr/>max<wbr/>Analog<wbr/>Sensitivity</a>,<wbr/> the camera device
+is guaranteed to use only analog amplification for applying the gain.<wbr/></p>
+<p>If the camera device cannot apply the exact sensitivity
+requested,<wbr/> it will reduce the gain to the nearest supported
+value.<wbr/> The final sensitivity used will be available in the
+output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>ISO 12232:2006 REI method is acceptable.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.sensor.testPatternData">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Data
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A pixel <code>[R,<wbr/> G_<wbr/>even,<wbr/> G_<wbr/>odd,<wbr/> B]</code> that supplies the test pattern
+when <a href="#controls_android.sensor.testPatternMode">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode</a> is SOLID_<wbr/>COLOR.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Each color channel is treated as an unsigned 32-bit integer.<wbr/>
+The camera device then uses the most significant X bits
+that correspond to how many bits are in its Bayer raw sensor
+output.<wbr/></p>
+<p>For example,<wbr/> a sensor with RAW10 Bayer output would use the
+10 most significant bits from each color channel.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.sensor.testPatternMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No test pattern mode is used,<wbr/> and the camera
+device returns captures from the image sensor.<wbr/></p>
+<p>This is the default if the key is not set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SOLID_COLOR</span>
+                    <span class="entry_type_enum_notes"><p>Each pixel in <code>[R,<wbr/> G_<wbr/>even,<wbr/> G_<wbr/>odd,<wbr/> B]</code> is replaced by its
+respective color channel provided in
+<a href="#controls_android.sensor.testPatternData">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Data</a>.<wbr/></p>
+<p>For example:</p>
+<pre><code>android.<wbr/>testPatternData = [0,<wbr/> 0xFFFFFFFF,<wbr/> 0xFFFFFFFF,<wbr/> 0]
+</code></pre>
+<p>All green pixels are 100% green.<wbr/> All red/<wbr/>blue pixels are black.<wbr/></p>
+<pre><code>android.<wbr/>testPatternData = [0xFFFFFFFF,<wbr/> 0,<wbr/> 0xFFFFFFFF,<wbr/> 0]
+</code></pre>
+<p>All red pixels are 100% red.<wbr/> Only the odd green pixels
+are 100% green.<wbr/> All blue pixels are 100% black.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">COLOR_BARS</span>
+                    <span class="entry_type_enum_notes"><p>All pixel data is replaced with an 8-bar color pattern.<wbr/></p>
+<p>The vertical bars (left-to-right) are as follows:</p>
+<ul>
+<li>100% white</li>
+<li>yellow</li>
+<li>cyan</li>
+<li>green</li>
+<li>magenta</li>
+<li>red</li>
+<li>blue</li>
+<li>black</li>
+</ul>
+<p>In general the image would look like the following:</p>
+<pre><code>W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+
+(B = Blue,<wbr/> K = Black)
+</code></pre>
+<p>Each bar should take up 1/<wbr/>8 of the sensor pixel array width.<wbr/>
+When this is not possible,<wbr/> the bar size should be rounded
+down to the nearest integer and the pattern can repeat
+on the right side.<wbr/></p>
+<p>Each bar's height must always take up the full sensor
+pixel array height.<wbr/></p>
+<p>Each pixel in this test pattern must be set to either
+0% intensity or 100% intensity.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">COLOR_BARS_FADE_TO_GRAY</span>
+                    <span class="entry_type_enum_notes"><p>The test pattern is similar to COLOR_<wbr/>BARS,<wbr/> except that
+each bar should start at its specified color at the top,<wbr/>
+and fade to gray at the bottom.<wbr/></p>
+<p>Furthermore each bar is further subdivided into a left and
+right half.<wbr/> The left half should have a smooth gradient,<wbr/>
+and the right half should have a quantized gradient.<wbr/></p>
+<p>In particular,<wbr/> the right half's should consist of blocks of the
+same color for 1/<wbr/>16th active sensor pixel array width.<wbr/></p>
+<p>The least significant bits in the quantized gradient should
+be copied from the most significant bits of the smooth gradient.<wbr/></p>
+<p>The height of each bar should always be a multiple of 128.<wbr/>
+When this is not the case,<wbr/> the pattern should repeat at the bottom
+of the image.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PN9</span>
+                    <span class="entry_type_enum_notes"><p>All pixel data is replaced by a pseudo-random sequence
+generated from a PN9 512-bit sequence (typically implemented
+in hardware with a linear feedback shift register).<wbr/></p>
+<p>The generator should be reset at the beginning of each frame,<wbr/>
+and thus each subsequent raw frame with this test pattern should
+be exactly the same as the last.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CUSTOM1</span>
+                    <span class="entry_type_enum_value">256</span>
+                    <span class="entry_type_enum_notes"><p>The first custom test pattern.<wbr/> All custom patterns that are
+available only on this camera device are at least this numeric
+value.<wbr/></p>
+<p>All of the custom test patterns will be static
+(that is the raw image must not vary from frame to frame).<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>When enabled,<wbr/> the sensor sends a test pattern instead of
+doing a real exposure from the camera.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.availableTestPatternModes">android.<wbr/>sensor.<wbr/>available<wbr/>Test<wbr/>Pattern<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When a test pattern is enabled,<wbr/> all manual sensor controls specified
+by android.<wbr/>sensor.<wbr/>* will be ignored.<wbr/> All other controls should
+work as normal.<wbr/></p>
+<p>For example,<wbr/> if manual flash is enabled,<wbr/> flash firing should still
+occur (and that the test pattern remain unmodified,<wbr/> since the flash
+would not actually affect it).<wbr/></p>
+<p>Defaults to OFF.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All test patterns are specified in the Bayer domain.<wbr/></p>
+<p>The HAL may choose to substitute test patterns from the sensor
+with test patterns from on-device memory.<wbr/> In that case,<wbr/> it should be
+indistinguishable to the ISP whether the data came from the
+sensor interconnect bus (such as CSI2) or memory.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+                
+            
+
+                
+          <tr class="entry" id="static_android.sensor.info.activeArraySize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">Four ints defining the active pixel rectangle</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The area of the image sensor which corresponds to active pixels after any geometric
+distortion correction has been applied.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates on the image sensor
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is the rectangle representing the size of the active region of the sensor (i.<wbr/>e.<wbr/>
+the region that actually receives light from the scene) after any geometric correction
+has been applied,<wbr/> and should be treated as the maximum size in pixels of any of the
+image output formats aside from the raw formats.<wbr/></p>
+<p>This rectangle is defined relative to the full pixel array; (0,<wbr/>0) is the top-left of
+the full pixel array,<wbr/> and the size of the full pixel array is given by
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The coordinate system for most other keys that list pixel coordinates,<wbr/> including
+<a href="#controls_android.scaler.cropRegion">android.<wbr/>scaler.<wbr/>crop<wbr/>Region</a>,<wbr/> is defined relative to the active array rectangle given in
+this field,<wbr/> with <code>(0,<wbr/> 0)</code> being the top-left of this rectangle.<wbr/></p>
+<p>The active array may be smaller than the full pixel array,<wbr/> since the full array may
+include black calibration pixels or other inactive regions,<wbr/> and geometric correction
+resulting in scaling or cropping may have been applied.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This array contains <code>(xmin,<wbr/> ymin,<wbr/> width,<wbr/> height)</code>.<wbr/> The <code>(xmin,<wbr/> ymin)</code> must be
+&gt;= <code>(0,<wbr/>0)</code>.<wbr/>
+The <code>(width,<wbr/> height)</code> must be &lt;= <code><a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a></code>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.sensitivityRange">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeInt]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">Range of supported sensitivities</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Range of sensitivities for <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> supported by this
+camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Min &lt;= 100,<wbr/> Max &gt;= 800</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The values are the standard ISO sensitivity values,<wbr/>
+as defined in ISO 12232:2006.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.colorFilterArrangement">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">RGGB</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">GRBG</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">GBRG</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">BGGR</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">RGB</span>
+                    <span class="entry_type_enum_notes"><p>Sensor is not Bayer; output has 3 16-bit
+values for each pixel,<wbr/> instead of just 1 16-bit value
+per pixel.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The arrangement of color filters on sensor;
+represents the colors in the top-left 2x2 section of
+the sensor,<wbr/> in reading order.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.exposureTimeRange">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as rangeLong]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">nanoseconds</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The range of image exposure times for <a href="#controls_android.sensor.exposureTime">android.<wbr/>sensor.<wbr/>exposure<wbr/>Time</a> supported
+by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>The minimum exposure time will be less than 100 us.<wbr/> For FULL
+capability devices (<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL),<wbr/>
+the maximum exposure time will be greater than 100ms.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For FULL capability devices (<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL),<wbr/>
+The maximum of the range SHOULD be at least 1 second (1e9),<wbr/> MUST be at least
+100ms.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.maxFrameDuration">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum possible frame duration (minimum frame rate) for
+<a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> that is supported this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>For FULL capability devices
+(<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL),<wbr/> at least 100ms.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Attempting to use frame durations beyond the maximum will result in the frame
+duration being clipped to the maximum.<wbr/> See that control for a full definition of frame
+durations.<wbr/></p>
+<p>Refer to <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>
+for the minimum frame duration values.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For FULL capability devices (<a href="#static_android.info.supportedHardwareLevel">android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level</a> == FULL),<wbr/>
+The maximum of the range SHOULD be at least
+1 second (1e9),<wbr/> MUST be at least 100ms (100e6).<wbr/></p>
+<p><a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a> must be greater or
+equal to the <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a> max
+value (since exposure time overrides frame duration).<wbr/></p>
+<p>Available minimum frame durations for JPEG must be no greater
+than that of the YUV_<wbr/>420_<wbr/>888/<wbr/>IMPLEMENTATION_<wbr/>DEFINED
+minimum frame durations (for that respective size).<wbr/></p>
+<p>Since JPEG processing is considered offline and can take longer than
+a single uncompressed capture,<wbr/> refer to
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a>
+for details about encoding this scenario.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.physicalSize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>physical<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as sizeF]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">width x height</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The physical dimensions of the full pixel
+array.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Millimeters
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is the physical size of the sensor pixel
+array defined by <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Needed for FOV calculation for old API</p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.pixelArraySize">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [public as size]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Dimensions of the full pixel array,<wbr/> possibly
+including black calibration pixels.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixels
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The pixel count of the full pixel array of the image sensor,<wbr/> which covers
+<a href="#static_android.sensor.info.physicalSize">android.<wbr/>sensor.<wbr/>info.<wbr/>physical<wbr/>Size</a> area.<wbr/>  This represents the full pixel dimensions of
+the raw buffers produced by this sensor.<wbr/></p>
+<p>If a camera device supports raw sensor formats,<wbr/> either this or
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> is the maximum dimensions for the raw
+output formats listed in <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> (this depends on
+whether or not the image sensor returns buffers containing pixels that are not
+part of the active array region for blacklevel calibration or other purposes).<wbr/></p>
+<p>Some parts of the full pixel array may not receive light from the scene,<wbr/>
+or be otherwise inactive.<wbr/>  The <a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> key
+defines the rectangle of active pixels that will be included in processed image
+formats.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.whiteLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum raw value output by sensor.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt; 255 (8-bit output)</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This specifies the fully-saturated encoding level for the raw
+sample values from the sensor.<wbr/>  This is typically caused by the
+sensor becoming highly non-linear or clipping.<wbr/> The minimum for
+each channel is specified by the offset in the
+<a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> key.<wbr/></p>
+<p>The white level is typically determined either by sensor bit depth
+(8-14 bits is expected),<wbr/> or by the point where the sensor response
+becomes too non-linear to be useful.<wbr/>  The default value for this is
+maximum representable value for a 16-bit raw sample (2^16 - 1).<wbr/></p>
+<p>The white level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended
+to use <a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> for captures when supported
+by the camera device,<wbr/> which provides more accurate white level values.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The full bit depth of the sensor must be available in the raw data,<wbr/>
+so the value for linear sensors should not be significantly lower
+than maximum raw value supported,<wbr/> i.<wbr/>e.<wbr/> 2^(sensor bits per pixel).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.timestampSource">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>timestamp<wbr/>Source
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">UNKNOWN</span>
+                    <span class="entry_type_enum_notes"><p>Timestamps from <a href="#dynamic_android.sensor.timestamp">android.<wbr/>sensor.<wbr/>timestamp</a> are in nanoseconds and monotonic,<wbr/>
+but can not be compared to timestamps from other subsystems
+(e.<wbr/>g.<wbr/> accelerometer,<wbr/> gyro etc.<wbr/>),<wbr/> or other instances of the same or different
+camera devices in the same system.<wbr/> Timestamps between streams and results for
+a single camera instance are comparable,<wbr/> and the timestamps for all buffers
+and the result metadata generated by a single capture are identical.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">REALTIME</span>
+                    <span class="entry_type_enum_notes"><p>Timestamps from <a href="#dynamic_android.sensor.timestamp">android.<wbr/>sensor.<wbr/>timestamp</a> are in the same timebase as
+<a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,<wbr/>
+and they can be compared to other timestamps using that base.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The time base source for sensor capture start timestamps.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The timestamps provided for captures are always in nanoseconds and monotonic,<wbr/> but
+may not based on a time source that can be compared to other system time sources.<wbr/></p>
+<p>This characteristic defines the source for the timestamps,<wbr/> and therefore whether they
+can be compared against other system time sources/<wbr/>timestamps.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For camera devices implement UNKNOWN,<wbr/> the camera framework expects that the timestamp
+source to be SYSTEM_<wbr/>TIME_<wbr/>MONOTONIC.<wbr/> For camera devices implement REALTIME,<wbr/> the camera
+framework expects that the timestamp source to be SYSTEM_<wbr/>TIME_<wbr/>BOOTTIME.<wbr/> See
+system/<wbr/>core/<wbr/>include/<wbr/>utils/<wbr/>Timers.<wbr/>h for the definition of SYSTEM_<wbr/>TIME_<wbr/>MONOTONIC and
+SYSTEM_<wbr/>TIME_<wbr/>BOOTTIME.<wbr/> Note that HAL must follow above expectation; otherwise video
+recording might suffer unexpected behavior.<wbr/></p>
+<p>Also,<wbr/> camera devices implements REALTIME must pass the ITS sensor fusion test which
+tests the alignment between camera timestamps and gyro sensor timestamps.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.lensShadingApplied">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the RAW images output from this camera device are subject to
+lens shading correction.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If TRUE,<wbr/> all images produced by the camera device in the RAW image formats will
+have lens shading correction already applied to it.<wbr/> If FALSE,<wbr/> the images will
+not be adjusted for lens shading correction.<wbr/>
+See <a href="#static_android.request.maxNumOutputRaw">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Raw</a> for a list of RAW image formats.<wbr/></p>
+<p>This key will be <code>null</code> for all devices do not report this information.<wbr/>
+Devices with RAW capability will always report this information in this key.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.info.preCorrectionActiveArraySize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">Four ints defining the active pixel rectangle</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The area of the image sensor which corresponds to active pixels prior to the
+application of any geometric distortion correction.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Pixel coordinates on the image sensor
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is the rectangle representing the size of the active region of the sensor (i.<wbr/>e.<wbr/>
+the region that actually receives light from the scene) before any geometric correction
+has been applied,<wbr/> and should be treated as the active region rectangle for any of the
+raw formats.<wbr/>  All metadata associated with raw processing (e.<wbr/>g.<wbr/> the lens shading
+correction map,<wbr/> and radial distortion fields) treats the top,<wbr/> left of this rectangle as
+the origin,<wbr/> (0,<wbr/>0).<wbr/></p>
+<p>The size of this region determines the maximum field of view and the maximum number of
+pixels that an image from this sensor can contain,<wbr/> prior to the application of
+geometric distortion correction.<wbr/> The effective maximum pixel dimensions of a
+post-distortion-corrected image is given by the <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>
+field,<wbr/> and the effective maximum field of view for a post-distortion-corrected image
+can be calculated by applying the geometric distortion correction fields to this
+rectangle,<wbr/> and cropping to the rectangle given in <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>E.<wbr/>g.<wbr/> to calculate position of a pixel,<wbr/> (x,<wbr/>y),<wbr/> in a processed YUV output image with the
+dimensions in <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> given the position of a pixel,<wbr/>
+(x',<wbr/> y'),<wbr/> in the raw pixel array with dimensions give in
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>:</p>
+<ol>
+<li>Choose a pixel (x',<wbr/> y') within the active array region of the raw buffer given in
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>,<wbr/> otherwise this pixel is considered
+to be outside of the FOV,<wbr/> and will not be shown in the processed output image.<wbr/></li>
+<li>Apply geometric distortion correction to get the post-distortion pixel coordinate,<wbr/>
+(x_<wbr/>i,<wbr/> y_<wbr/>i).<wbr/> When applying geometric correction metadata,<wbr/> note that metadata for raw
+buffers is defined relative to the top,<wbr/> left of the
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> rectangle.<wbr/></li>
+<li>If the resulting corrected pixel coordinate is within the region given in
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>,<wbr/> then the position of this pixel in the
+processed output image buffer is <code>(x_<wbr/>i - activeArray.<wbr/>left,<wbr/> y_<wbr/>i - activeArray.<wbr/>top)</code>,<wbr/>
+when the top,<wbr/> left coordinate of that buffer is treated as (0,<wbr/> 0).<wbr/></li>
+</ol>
+<p>Thus,<wbr/> for pixel x',<wbr/>y' = (25,<wbr/> 25) on a sensor where <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>
+is (100,<wbr/>100),<wbr/> <a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a> is (10,<wbr/> 10,<wbr/> 100,<wbr/> 100),<wbr/>
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a> is (20,<wbr/> 20,<wbr/> 80,<wbr/> 80),<wbr/> and the geometric distortion
+correction doesn't change the pixel coordinate,<wbr/> the resulting pixel selected in
+pixel coordinates would be x,<wbr/>y = (25,<wbr/> 25) relative to the top,<wbr/>left of the raw buffer
+with dimensions given in <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>,<wbr/> and would be (5,<wbr/> 5)
+relative to the top,<wbr/>left of post-processed YUV output buffer with dimensions given in
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The currently supported fields that correct for geometric distortion are:</p>
+<ol>
+<li><a href="#static_android.lens.radialDistortion">android.<wbr/>lens.<wbr/>radial<wbr/>Distortion</a>.<wbr/></li>
+</ol>
+<p>If all of the geometric distortion fields are no-ops,<wbr/> this rectangle will be the same
+as the post-distortion-corrected rectangle given in
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>This rectangle is defined relative to the full pixel array; (0,<wbr/>0) is the top-left of
+the full pixel array,<wbr/> and the size of the full pixel array is given by
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The pre-correction active array may be smaller than the full pixel array,<wbr/> since the
+full array may include black calibration pixels or other inactive regions.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This array contains <code>(xmin,<wbr/> ymin,<wbr/> width,<wbr/> height)</code>.<wbr/> The <code>(xmin,<wbr/> ymin)</code> must be
+&gt;= <code>(0,<wbr/>0)</code>.<wbr/>
+The <code>(width,<wbr/> height)</code> must be &lt;= <code><a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a></code>.<wbr/></p>
+<p>If omitted by the HAL implementation,<wbr/> the camera framework will assume that this is
+the same as the post-correction active array region given in
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+        
+
+                
+          <tr class="entry" id="static_android.sensor.referenceIlluminant1">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">DAYLIGHT</span>
+                    <span class="entry_type_enum_value">1</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FLUORESCENT</span>
+                    <span class="entry_type_enum_value">2</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TUNGSTEN</span>
+                    <span class="entry_type_enum_value">3</span>
+                    <span class="entry_type_enum_notes"><p>Incandescent light</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FLASH</span>
+                    <span class="entry_type_enum_value">4</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FINE_WEATHER</span>
+                    <span class="entry_type_enum_value">9</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CLOUDY_WEATHER</span>
+                    <span class="entry_type_enum_value">10</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SHADE</span>
+                    <span class="entry_type_enum_value">11</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DAYLIGHT_FLUORESCENT</span>
+                    <span class="entry_type_enum_value">12</span>
+                    <span class="entry_type_enum_notes"><p>D 5700 - 7100K</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">DAY_WHITE_FLUORESCENT</span>
+                    <span class="entry_type_enum_value">13</span>
+                    <span class="entry_type_enum_notes"><p>N 4600 - 5400K</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">COOL_WHITE_FLUORESCENT</span>
+                    <span class="entry_type_enum_value">14</span>
+                    <span class="entry_type_enum_notes"><p>W 3900 - 4500K</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">WHITE_FLUORESCENT</span>
+                    <span class="entry_type_enum_value">15</span>
+                    <span class="entry_type_enum_notes"><p>WW 3200 - 3700K</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STANDARD_A</span>
+                    <span class="entry_type_enum_value">17</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STANDARD_B</span>
+                    <span class="entry_type_enum_value">18</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">STANDARD_C</span>
+                    <span class="entry_type_enum_value">19</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">D55</span>
+                    <span class="entry_type_enum_value">20</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">D65</span>
+                    <span class="entry_type_enum_value">21</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">D75</span>
+                    <span class="entry_type_enum_value">22</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">D50</span>
+                    <span class="entry_type_enum_value">23</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ISO_STUDIO_TUNGSTEN</span>
+                    <span class="entry_type_enum_value">24</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The standard reference illuminant used as the scene light source when
+calculating the <a href="#static_android.sensor.colorTransform1">android.<wbr/>sensor.<wbr/>color<wbr/>Transform1</a>,<wbr/>
+<a href="#static_android.sensor.calibrationTransform1">android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform1</a>,<wbr/> and
+<a href="#static_android.sensor.forwardMatrix1">android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix1</a> matrices.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The values in this key correspond to the values defined for the
+EXIF LightSource tag.<wbr/> These illuminants are standard light sources
+that are often used calibrating camera devices.<wbr/></p>
+<p>If this key is present,<wbr/> then <a href="#static_android.sensor.colorTransform1">android.<wbr/>sensor.<wbr/>color<wbr/>Transform1</a>,<wbr/>
+<a href="#static_android.sensor.calibrationTransform1">android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform1</a>,<wbr/> and
+<a href="#static_android.sensor.forwardMatrix1">android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix1</a> will also be present.<wbr/></p>
+<p>Some devices may choose to provide a second set of calibration
+information for improved quality,<wbr/> including
+<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a> and its corresponding matrices.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The first reference illuminant (<a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a>)
+and corresponding matrices must be present to support the RAW capability
+and DNG output.<wbr/></p>
+<p>When producing raw images with a color profile that has only been
+calibrated against a single light source,<wbr/> it is valid to omit
+<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a> along with the
+<a href="#static_android.sensor.colorTransform2">android.<wbr/>sensor.<wbr/>color<wbr/>Transform2</a>,<wbr/> <a href="#static_android.sensor.calibrationTransform2">android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform2</a>,<wbr/>
+and <a href="#static_android.sensor.forwardMatrix2">android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix2</a> matrices.<wbr/></p>
+<p>If only <a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a> is included,<wbr/> it should be
+chosen so that it is representative of typical scene lighting.<wbr/>  In
+general,<wbr/> D50 or DAYLIGHT will be chosen for this case.<wbr/></p>
+<p>If both <a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a> and
+<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a> are included,<wbr/> they should be
+chosen to represent the typical range of scene lighting conditions.<wbr/>
+In general,<wbr/> low color temperature illuminant such as Standard-A will
+be chosen for the first reference illuminant and a higher color
+temperature illuminant such as D65 will be chosen for the second
+reference illuminant.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.referenceIlluminant2">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The standard reference illuminant used as the scene light source when
+calculating the <a href="#static_android.sensor.colorTransform2">android.<wbr/>sensor.<wbr/>color<wbr/>Transform2</a>,<wbr/>
+<a href="#static_android.sensor.calibrationTransform2">android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform2</a>,<wbr/> and
+<a href="#static_android.sensor.forwardMatrix2">android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix2</a> matrices.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>See <a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a> for more details.<wbr/></p>
+<p>If this key is present,<wbr/> then <a href="#static_android.sensor.colorTransform2">android.<wbr/>sensor.<wbr/>color<wbr/>Transform2</a>,<wbr/>
+<a href="#static_android.sensor.calibrationTransform2">android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform2</a>,<wbr/> and
+<a href="#static_android.sensor.forwardMatrix2">android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix2</a> will also be present.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.calibrationTransform1">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform1
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A per-device calibration transform matrix that maps from the
+reference sensor colorspace to the actual device sensor colorspace.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to correct for per-device variations in the
+sensor colorspace,<wbr/> and is used for processing raw buffer data.<wbr/></p>
+<p>The matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and
+contains a per-device calibration transform that maps colors
+from reference sensor color space (i.<wbr/>e.<wbr/> the "golden module"
+colorspace) into this camera device's native sensor color
+space under the first reference illuminant
+(<a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a>).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.calibrationTransform2">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>calibration<wbr/>Transform2
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A per-device calibration transform matrix that maps from the
+reference sensor colorspace to the actual device sensor colorspace
+(this is the colorspace of the raw buffer data).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to correct for per-device variations in the
+sensor colorspace,<wbr/> and is used for processing raw buffer data.<wbr/></p>
+<p>The matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and
+contains a per-device calibration transform that maps colors
+from reference sensor color space (i.<wbr/>e.<wbr/> the "golden module"
+colorspace) into this camera device's native sensor color
+space under the second reference illuminant
+(<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a>).<wbr/></p>
+<p>This matrix will only be present if the second reference
+illuminant is present.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.colorTransform1">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>color<wbr/>Transform1
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A matrix that transforms color values from CIE XYZ color space to
+reference sensor color space.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to convert from the standard CIE XYZ color
+space to the reference sensor colorspace,<wbr/> and is used when processing
+raw buffer data.<wbr/></p>
+<p>The matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and
+contains a color transform matrix that maps colors from the CIE
+XYZ color space to the reference sensor color space (i.<wbr/>e.<wbr/> the
+"golden module" colorspace) under the first reference illuminant
+(<a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a>).<wbr/></p>
+<p>The white points chosen in both the reference sensor color space
+and the CIE XYZ colorspace when calculating this transform will
+match the standard white point for the first reference illuminant
+(i.<wbr/>e.<wbr/> no chromatic adaptation will be applied by this transform).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.colorTransform2">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>color<wbr/>Transform2
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A matrix that transforms color values from CIE XYZ color space to
+reference sensor color space.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to convert from the standard CIE XYZ color
+space to the reference sensor colorspace,<wbr/> and is used when processing
+raw buffer data.<wbr/></p>
+<p>The matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and
+contains a color transform matrix that maps colors from the CIE
+XYZ color space to the reference sensor color space (i.<wbr/>e.<wbr/> the
+"golden module" colorspace) under the second reference illuminant
+(<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a>).<wbr/></p>
+<p>The white points chosen in both the reference sensor color space
+and the CIE XYZ colorspace when calculating this transform will
+match the standard white point for the second reference illuminant
+(i.<wbr/>e.<wbr/> no chromatic adaptation will be applied by this transform).<wbr/></p>
+<p>This matrix will only be present if the second reference
+illuminant is present.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.forwardMatrix1">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix1
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A matrix that transforms white balanced camera colors from the reference
+sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to convert to the standard CIE XYZ colorspace,<wbr/> and
+is used when processing raw buffer data.<wbr/></p>
+<p>This matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and contains
+a color transform matrix that maps white balanced colors from the
+reference sensor color space to the CIE XYZ color space with a D50 white
+point.<wbr/></p>
+<p>Under the first reference illuminant (<a href="#static_android.sensor.referenceIlluminant1">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant1</a>)
+this matrix is chosen so that the standard white point for this reference
+illuminant in the reference sensor colorspace is mapped to D50 in the
+CIE XYZ colorspace.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.forwardMatrix2">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>forward<wbr/>Matrix2
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [public as colorSpaceTransform]</span>
+
+
+
+
+                <div class="entry_type_notes">3x3 matrix in row-major-order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A matrix that transforms white balanced camera colors from the reference
+sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This matrix is used to convert to the standard CIE XYZ colorspace,<wbr/> and
+is used when processing raw buffer data.<wbr/></p>
+<p>This matrix is expressed as a 3x3 matrix in row-major-order,<wbr/> and contains
+a color transform matrix that maps white balanced colors from the
+reference sensor color space to the CIE XYZ color space with a D50 white
+point.<wbr/></p>
+<p>Under the second reference illuminant (<a href="#static_android.sensor.referenceIlluminant2">android.<wbr/>sensor.<wbr/>reference<wbr/>Illuminant2</a>)
+this matrix is chosen so that the standard white point for this reference
+illuminant in the reference sensor colorspace is mapped to D50 in the
+CIE XYZ colorspace.<wbr/></p>
+<p>This matrix will only be present if the second reference
+illuminant is present.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.baseGainFactor">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>sensor.<wbr/>base<wbr/>Gain<wbr/>Factor
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Gain factor from electrons to raw units when
+ISO=100</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.blackLevelPattern">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public as blackLevelPattern]</span>
+
+
+
+
+                <div class="entry_type_notes">2x2 raw count block</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A fixed black level offset for each of the color filter arrangement
+(CFA) mosaic channels.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0 for each.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key specifies the zero light value for each of the CFA mosaic
+channels in the camera sensor.<wbr/>  The maximal value output by the
+sensor is represented by the value in <a href="#static_android.sensor.info.whiteLevel">android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level</a>.<wbr/></p>
+<p>The values are given in the same order as channels listed for the CFA
+layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
+nth value given corresponds to the black level offset for the nth
+color channel listed in the CFA.<wbr/></p>
+<p>The black level values of captured images may vary for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> This key
+represents a coarse approximation for such case.<wbr/> It is recommended to
+use <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> or use pixels from
+<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> directly for captures when
+supported by the camera device,<wbr/> which provides more accurate black
+level values.<wbr/> For raw capture in particular,<wbr/> it is recommended to use
+pixels from <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> to calculate black
+level values for each frame.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The values are given in row-column scan order,<wbr/> with the first value
+corresponding to the element of the CFA in row=0,<wbr/> column=0.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.maxAnalogSensitivity">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>max<wbr/>Analog<wbr/>Sensitivity
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum sensitivity that is implemented
+purely through analog gain.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_FULL">FULL</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a> values less than or
+equal to this,<wbr/> all applied gain must be analog.<wbr/> For
+values above this,<wbr/> the gain applied can be a mix of analog and
+digital.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.orientation">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>orientation
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Clockwise angle through which the output image needs to be rotated to be
+upright on the device screen in its native orientation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Degrees of clockwise rotation; always a multiple of
+          90
+            </td>
+
+            <td class="entry_range">
+              <p>0,<wbr/> 90,<wbr/> 180,<wbr/> 270</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Also defines the direction of rolling shutter readout,<wbr/> which is from top to bottom in
+the sensor's coordinate system.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.profileHueSatMapDimensions">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>profile<wbr/>Hue<wbr/>Sat<wbr/>Map<wbr/>Dimensions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+                <div class="entry_type_notes">Number of samples for hue,<wbr/> saturation,<wbr/> and value</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The number of input samples for each dimension of
+<a href="#dynamic_android.sensor.profileHueSatMap">android.<wbr/>sensor.<wbr/>profile<wbr/>Hue<wbr/>Sat<wbr/>Map</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Hue &gt;= 1,<wbr/>
+Saturation &gt;= 2,<wbr/>
+Value &gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The number of input samples for the hue,<wbr/> saturation,<wbr/> and value
+dimension of <a href="#dynamic_android.sensor.profileHueSatMap">android.<wbr/>sensor.<wbr/>profile<wbr/>Hue<wbr/>Sat<wbr/>Map</a>.<wbr/> The order of the
+dimensions given is hue,<wbr/> saturation,<wbr/> value; where hue is the 0th
+element.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.availableTestPatternModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>available<wbr/>Test<wbr/>Pattern<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of sensor test pattern modes for <a href="#controls_android.sensor.testPatternMode">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode</a>
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.sensor.testPatternMode">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Defaults to OFF,<wbr/> and always includes OFF if defined.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All custom modes must be &gt;= CUSTOM1.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.opticalBlackRegions">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x num_regions
+                </span>
+              <span class="entry_type_visibility"> [public as rectangle]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of disjoint rectangles indicating the sensor
+optically shielded black pixel regions.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>In most camera sensors,<wbr/> the active array is surrounded by some
+optically shielded pixel areas.<wbr/> By blocking light,<wbr/> these pixels
+provides a reliable black reference for black level compensation
+in active array region.<wbr/></p>
+<p>This key provides a list of disjoint rectangles specifying the
+regions of optically shielded (with metal shield) black pixel
+regions if the camera device is capable of reading out these black
+pixels in the output raw images.<wbr/> In comparison to the fixed black
+level values reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a>,<wbr/> this key
+may provide a more accurate way for the application to calculate
+black level of each captured raw images.<wbr/></p>
+<p>When this key is reported,<wbr/> the <a href="#dynamic_android.sensor.dynamicBlackLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level</a> and
+<a href="#dynamic_android.sensor.dynamicWhiteLevel">android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level</a> will also be reported.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This array contains (xmin,<wbr/> ymin,<wbr/> width,<wbr/> height).<wbr/> The (xmin,<wbr/> ymin)
+must be &gt;= (0,<wbr/>0) and &lt;=
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> The (width,<wbr/> height) must be
+&lt;= <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/> Each region must be
+outside the region reported by
+<a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pre<wbr/>Correction<wbr/>Active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>The HAL must report minimal number of disjoint regions for the
+optically shielded back pixel regions.<wbr/> For example,<wbr/> if a region can
+be covered by one rectangle,<wbr/> the HAL must not split this region into
+multiple rectangles.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.sensor.opaqueRawSize">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>opaque<wbr/>Raw<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Size in bytes for all the listed opaque RAW buffer sizes</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Must be large enough to fit the opaque RAW of corresponding size produced by
+the camera</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This configurations are listed as <code>(width,<wbr/> height,<wbr/> size_<wbr/>in_<wbr/>bytes)</code> tuples.<wbr/>
+This is used for sizing the gralloc buffers for opaque RAW buffers.<wbr/>
+All RAW_<wbr/>OPAQUE output stream configuration listed in
+<a href="#static_android.scaler.availableStreamConfigurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stream<wbr/>Configurations</a> will have a corresponding tuple in
+this key.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key is added in HAL3.<wbr/>4.<wbr/>
+For HAL3.<wbr/>4 or above: devices advertising RAW_<wbr/>OPAQUE format output must list this key.<wbr/>
+For HAL3.<wbr/>3 or earlier devices: if RAW_<wbr/>OPAQUE ouput is advertised,<wbr/> camera framework
+will derive this key by assuming each pixel takes two bytes and no padding bytes
+between rows.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.sensor.exposureTime">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>exposure<wbr/>Time
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Duration each pixel is exposed to
+light.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the sensor can't expose this exact duration,<wbr/> it will shorten the
+duration exposed to the nearest possible value (rather than expose longer).<wbr/>
+The final exposure time used will be available in the output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.frameDuration">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>frame<wbr/>Duration
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Duration from start of frame exposure to
+start of next frame exposure.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>See <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a>,<wbr/>
+<a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a>.<wbr/> The duration
+is capped to <code>max(duration,<wbr/> exposureTime + overhead)</code>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The maximum frame rate that can be supported by a camera subsystem is
+a function of many factors:</p>
+<ul>
+<li>Requested resolutions of output image streams</li>
+<li>Availability of binning /<wbr/> skipping modes on the imager</li>
+<li>The bandwidth of the imager interface</li>
+<li>The bandwidth of the various ISP processing blocks</li>
+</ul>
+<p>Since these factors can vary greatly between different ISPs and
+sensors,<wbr/> the camera abstraction tries to represent the bandwidth
+restrictions with as simple a model as possible.<wbr/></p>
+<p>The model presented has the following characteristics:</p>
+<ul>
+<li>The image sensor is always configured to output the smallest
+resolution possible given the application's requested output stream
+sizes.<wbr/>  The smallest resolution is defined as being at least as large
+as the largest requested output stream size; the camera pipeline must
+never digitally upsample sensor data when the crop region covers the
+whole sensor.<wbr/> In general,<wbr/> this means that if only small output stream
+resolutions are configured,<wbr/> the sensor can provide a higher frame
+rate.<wbr/></li>
+<li>Since any request may use any or all the currently configured
+output streams,<wbr/> the sensor and ISP must be configured to support
+scaling a single capture to all the streams at the same time.<wbr/>  This
+means the camera pipeline must be ready to produce the largest
+requested output size without any delay.<wbr/>  Therefore,<wbr/> the overall
+frame rate of a given configured stream set is governed only by the
+largest requested stream resolution.<wbr/></li>
+<li>Using more than one output stream in a request does not affect the
+frame duration.<wbr/></li>
+<li>Certain format-streams may need to do additional background processing
+before data is consumed/<wbr/>produced by that stream.<wbr/> These processors
+can run concurrently to the rest of the camera pipeline,<wbr/> but
+cannot process more than 1 capture at a time.<wbr/></li>
+</ul>
+<p>The necessary information for the application,<wbr/> given the model above,<wbr/>
+is provided via the <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> field using
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>.<wbr/>
+These are used to determine the maximum frame rate /<wbr/> minimum frame
+duration that is possible for a given stream configuration.<wbr/></p>
+<p>Specifically,<wbr/> the application can use the following rules to
+determine the minimum frame duration it can request from the camera
+device:</p>
+<ol>
+<li>Let the set of currently configured input/<wbr/>output streams
+be called <code>S</code>.<wbr/></li>
+<li>Find the minimum frame durations for each stream in <code>S</code>,<wbr/> by looking
+it up in <a href="#static_android.scaler.streamConfigurationMap">android.<wbr/>scaler.<wbr/>stream<wbr/>Configuration<wbr/>Map</a> using <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>
+(with its respective size/<wbr/>format).<wbr/> Let this set of frame durations be
+called <code>F</code>.<wbr/></li>
+<li>For any given request <code>R</code>,<wbr/> the minimum frame duration allowed
+for <code>R</code> is the maximum out of all values in <code>F</code>.<wbr/> Let the streams
+used in <code>R</code> be called <code>S_<wbr/>r</code>.<wbr/></li>
+</ol>
+<p>If none of the streams in <code>S_<wbr/>r</code> have a stall time (listed in <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a>
+using its respective size/<wbr/>format),<wbr/> then the frame duration in <code>F</code>
+determines the steady state frame rate that the application will get
+if it uses <code>R</code> as a repeating request.<wbr/> Let this special kind of
+request be called <code>Rsimple</code>.<wbr/></p>
+<p>A repeating request <code>Rsimple</code> can be <em>occasionally</em> interleaved
+by a single capture of a new request <code>Rstall</code> (which has at least
+one in-use stream with a non-0 stall time) and if <code>Rstall</code> has the
+same minimum frame duration this will not cause a frame rate loss
+if all buffers from the previous <code>Rstall</code> have already been
+delivered.<wbr/></p>
+<p>For more details about stalling,<wbr/> see
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputStallDuration">StreamConfigurationMap#getOutputStallDuration</a>.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For more details about stalling,<wbr/> see
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.sensitivity">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>sensitivity
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of gain applied to sensor data
+before processing.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              ISO arithmetic units
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The sensitivity is the standard ISO sensitivity value,<wbr/>
+as defined in ISO 12232:2006.<wbr/></p>
+<p>The sensitivity must be within <a href="#static_android.sensor.info.sensitivityRange">android.<wbr/>sensor.<wbr/>info.<wbr/>sensitivity<wbr/>Range</a>,<wbr/> and
+if if it less than <a href="#static_android.sensor.maxAnalogSensitivity">android.<wbr/>sensor.<wbr/>max<wbr/>Analog<wbr/>Sensitivity</a>,<wbr/> the camera device
+is guaranteed to use only analog amplification for applying the gain.<wbr/></p>
+<p>If the camera device cannot apply the exact sensitivity
+requested,<wbr/> it will reduce the gain to the nearest supported
+value.<wbr/> The final sensitivity used will be available in the
+output capture result.<wbr/></p>
+<p>This control is only effective if <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> or <a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> is set to
+OFF; otherwise the auto-exposure algorithm will override this value.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>ISO 12232:2006 REI method is acceptable.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.timestamp">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>timestamp
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Time at start of exposure of first
+row of the image sensor active array,<wbr/> in nanoseconds.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>&gt; 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The timestamps are also included in all image
+buffers produced for the same capture,<wbr/> and will be identical
+on all the outputs.<wbr/></p>
+<p>When <a href="#static_android.sensor.info.timestampSource">android.<wbr/>sensor.<wbr/>info.<wbr/>timestamp<wbr/>Source</a> <code>==</code> UNKNOWN,<wbr/>
+the timestamps measure time since an unspecified starting point,<wbr/>
+and are monotonically increasing.<wbr/> They can be compared with the
+timestamps for other captures from the same camera device,<wbr/> but are
+not guaranteed to be comparable to any other time source.<wbr/></p>
+<p>When <a href="#static_android.sensor.info.timestampSource">android.<wbr/>sensor.<wbr/>info.<wbr/>timestamp<wbr/>Source</a> <code>==</code> REALTIME,<wbr/> the
+timestamps measure time in the same timebase as <a href="https://developer.android.com/reference/android/os/SystemClock.html#elapsedRealtimeNanos">SystemClock#elapsedRealtimeNanos</a>,<wbr/> and they can
+be compared to other timestamps from other subsystems that
+are using that base.<wbr/></p>
+<p>For reprocessing,<wbr/> the timestamp will match the start of exposure of
+the input image,<wbr/> i.<wbr/>e.<wbr/> <a href="https://developer.android.com/reference/CaptureResult.html#SENSOR_TIMESTAMP">the
+timestamp</a> in the TotalCaptureResult that was used to create the
+reprocess capture request.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All timestamps must be in reference to the kernel's
+CLOCK_<wbr/>BOOTTIME monotonic clock,<wbr/> which properly accounts for
+time spent asleep.<wbr/> This allows for synchronization with
+sensors that continue to operate while the system is
+otherwise asleep.<wbr/></p>
+<p>If <a href="#static_android.sensor.info.timestampSource">android.<wbr/>sensor.<wbr/>info.<wbr/>timestamp<wbr/>Source</a> <code>==</code> REALTIME,<wbr/>
+The timestamp must be synchronized with the timestamps from other
+sensor subsystems that are using the same timebase.<wbr/></p>
+<p>For reprocessing,<wbr/> the input image's start of exposure can be looked up
+with <a href="#dynamic_android.sensor.timestamp">android.<wbr/>sensor.<wbr/>timestamp</a> from the metadata included in the
+capture request.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.temperature">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>sensor.<wbr/>temperature
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The temperature of the sensor,<wbr/> sampled at the time
+exposure began for this frame.<wbr/></p>
+<p>The thermal diode being queried should be inside the sensor PCB,<wbr/> or
+somewhere close to it.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Celsius
+            </td>
+
+            <td class="entry_range">
+              <p>Optional.<wbr/> This value is missing if no temperature is available.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.neutralColorPoint">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>neutral<wbr/>Color<wbr/>Point
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The estimated camera neutral color in the native sensor colorspace at
+the time of capture.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value gives the neutral color point encoded as an RGB value in the
+native sensor color space.<wbr/>  The neutral color point indicates the
+currently estimated white point of the scene illumination.<wbr/>  It can be
+used to interpolate between the provided color transforms when
+processing raw sensor data.<wbr/></p>
+<p>The order of the values is R,<wbr/> G,<wbr/> B; where R is in the lowest index.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.noiseProfile">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>noise<wbr/>Profile
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">double</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2 x CFA Channels
+                </span>
+              <span class="entry_type_visibility"> [public as pairDoubleDouble]</span>
+
+
+
+
+                <div class="entry_type_notes">Pairs of noise model coefficients</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Noise model coefficients for each CFA mosaic channel.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key contains two noise model coefficients for each CFA channel
+corresponding to the sensor amplification (S) and sensor readout
+noise (O).<wbr/>  These are given as pairs of coefficients for each channel
+in the same order as channels listed for the CFA layout key
+(see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>).<wbr/>  This is
+represented as an array of Pair&lt;Double,<wbr/> Double&gt;,<wbr/> where
+the first member of the Pair at index n is the S coefficient and the
+second member is the O coefficient for the nth color channel in the CFA.<wbr/></p>
+<p>These coefficients are used in a two parameter noise model to describe
+the amount of noise present in the image for each CFA channel.<wbr/>  The
+noise model used here is:</p>
+<p>N(x) = sqrt(Sx + O)</p>
+<p>Where x represents the recorded signal of a CFA channel normalized to
+the range [0,<wbr/> 1],<wbr/> and S and O are the noise model coeffiecients for
+that channel.<wbr/></p>
+<p>A more detailed description of the noise model can be found in the
+Adobe DNG specification for the NoiseProfile tag.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For a CFA layout of RGGB,<wbr/> the list of coefficients would be given as
+an array of doubles S0,<wbr/>O0,<wbr/>S1,<wbr/>O1,...,<wbr/> where S0 and O0 are the coefficients
+for the red channel,<wbr/> S1 and O1 are the coefficients for the first green
+channel,<wbr/> etc.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.profileHueSatMap">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>profile<wbr/>Hue<wbr/>Sat<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  hue_samples x saturation_samples x value_samples x 3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+                <div class="entry_type_notes">Mapping for hue,<wbr/> saturation,<wbr/> and value</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A mapping containing a hue shift,<wbr/> saturation scale,<wbr/> and value scale
+for each pixel.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              
+          The hue shift is given in degrees; saturation and value scale factors are
+          unitless and are between 0 and 1 inclusive
+          
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>hue_<wbr/>samples,<wbr/> saturation_<wbr/>samples,<wbr/> and value_<wbr/>samples are given in
+<a href="#static_android.sensor.profileHueSatMapDimensions">android.<wbr/>sensor.<wbr/>profile<wbr/>Hue<wbr/>Sat<wbr/>Map<wbr/>Dimensions</a>.<wbr/></p>
+<p>Each entry of this map contains three floats corresponding to the
+hue shift,<wbr/> saturation scale,<wbr/> and value scale,<wbr/> respectively; where the
+hue shift has the lowest index.<wbr/> The map entries are stored in the key
+in nested loop order,<wbr/> with the value divisions in the outer loop,<wbr/> the
+hue divisions in the middle loop,<wbr/> and the saturation divisions in the
+inner loop.<wbr/> All zero input saturation entries are required to have a
+value scale factor of 1.<wbr/>0.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.profileToneCurve">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>sensor.<wbr/>profile<wbr/>Tone<wbr/>Curve
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  samples x 2
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+                <div class="entry_type_notes">Samples defining a spline for a tone-mapping curve</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A list of x,<wbr/>y samples defining a tone-mapping curve for gamma adjustment.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Each sample has an input range of <code>[0,<wbr/> 1]</code> and an output range of
+<code>[0,<wbr/> 1]</code>.<wbr/>  The first sample is required to be <code>(0,<wbr/> 0)</code>,<wbr/> and the last
+sample is required to be <code>(1,<wbr/> 1)</code>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This key contains a default tone curve that can be applied while
+processing the image as a starting point for user adjustments.<wbr/>
+The curve is specified as a list of value pairs in linear gamma.<wbr/>
+The curve is interpolated using a cubic spline.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.greenSplit">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>green<wbr/>Split
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The worst-case divergence between Bayer green channels.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value is an estimate of the worst case split between the
+Bayer green channels in the red and blue rows in the sensor color
+filter array.<wbr/></p>
+<p>The green split is calculated as follows:</p>
+<ol>
+<li>A 5x5 pixel (or larger) window W within the active sensor array is
+chosen.<wbr/> The term 'pixel' here is taken to mean a group of 4 Bayer
+mosaic channels (R,<wbr/> Gr,<wbr/> Gb,<wbr/> B).<wbr/>  The location and size of the window
+chosen is implementation defined,<wbr/> and should be chosen to provide a
+green split estimate that is both representative of the entire image
+for this camera sensor,<wbr/> and can be calculated quickly.<wbr/></li>
+<li>The arithmetic mean of the green channels from the red
+rows (mean_<wbr/>Gr) within W is computed.<wbr/></li>
+<li>The arithmetic mean of the green channels from the blue
+rows (mean_<wbr/>Gb) within W is computed.<wbr/></li>
+<li>The maximum ratio R of the two means is computed as follows:
+<code>R = max((mean_<wbr/>Gr + 1)/<wbr/>(mean_<wbr/>Gb + 1),<wbr/> (mean_<wbr/>Gb + 1)/<wbr/>(mean_<wbr/>Gr + 1))</code></li>
+</ol>
+<p>The ratio R is the green split divergence reported for this property,<wbr/>
+which represents how much the green channels differ in the mosaic
+pattern.<wbr/>  This value is typically used to determine the treatment of
+the green mosaic channels when demosaicing.<wbr/></p>
+<p>The green split value can be roughly interpreted as follows:</p>
+<ul>
+<li>R &lt; 1.<wbr/>03 is a negligible split (&lt;3% divergence).<wbr/></li>
+<li>1.<wbr/>20 &lt;= R &gt;= 1.<wbr/>03 will require some software
+correction to avoid demosaic errors (3-20% divergence).<wbr/></li>
+<li>R &gt; 1.<wbr/>20 will require strong software correction to produce
+a usuable image (&gt;20% divergence).<wbr/></li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The green split given may be a static value based on prior
+characterization of the camera sensor using the green split
+calculation method given here over a large,<wbr/> representative,<wbr/> sample
+set of images.<wbr/>  Other methods of calculation that produce equivalent
+results,<wbr/> and can be interpreted in the same manner,<wbr/> may be used.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.testPatternData">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Data
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A pixel <code>[R,<wbr/> G_<wbr/>even,<wbr/> G_<wbr/>odd,<wbr/> B]</code> that supplies the test pattern
+when <a href="#controls_android.sensor.testPatternMode">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode</a> is SOLID_<wbr/>COLOR.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Each color channel is treated as an unsigned 32-bit integer.<wbr/>
+The camera device then uses the most significant X bits
+that correspond to how many bits are in its Bayer raw sensor
+output.<wbr/></p>
+<p>For example,<wbr/> a sensor with RAW10 Bayer output would use the
+10 most significant bits from each color channel.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.testPatternMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No test pattern mode is used,<wbr/> and the camera
+device returns captures from the image sensor.<wbr/></p>
+<p>This is the default if the key is not set.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SOLID_COLOR</span>
+                    <span class="entry_type_enum_notes"><p>Each pixel in <code>[R,<wbr/> G_<wbr/>even,<wbr/> G_<wbr/>odd,<wbr/> B]</code> is replaced by its
+respective color channel provided in
+<a href="#controls_android.sensor.testPatternData">android.<wbr/>sensor.<wbr/>test<wbr/>Pattern<wbr/>Data</a>.<wbr/></p>
+<p>For example:</p>
+<pre><code>android.<wbr/>testPatternData = [0,<wbr/> 0xFFFFFFFF,<wbr/> 0xFFFFFFFF,<wbr/> 0]
+</code></pre>
+<p>All green pixels are 100% green.<wbr/> All red/<wbr/>blue pixels are black.<wbr/></p>
+<pre><code>android.<wbr/>testPatternData = [0xFFFFFFFF,<wbr/> 0,<wbr/> 0xFFFFFFFF,<wbr/> 0]
+</code></pre>
+<p>All red pixels are 100% red.<wbr/> Only the odd green pixels
+are 100% green.<wbr/> All blue pixels are 100% black.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">COLOR_BARS</span>
+                    <span class="entry_type_enum_notes"><p>All pixel data is replaced with an 8-bar color pattern.<wbr/></p>
+<p>The vertical bars (left-to-right) are as follows:</p>
+<ul>
+<li>100% white</li>
+<li>yellow</li>
+<li>cyan</li>
+<li>green</li>
+<li>magenta</li>
+<li>red</li>
+<li>blue</li>
+<li>black</li>
+</ul>
+<p>In general the image would look like the following:</p>
+<pre><code>W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+W Y C G M R B K
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+.<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/> .<wbr/>
+
+(B = Blue,<wbr/> K = Black)
+</code></pre>
+<p>Each bar should take up 1/<wbr/>8 of the sensor pixel array width.<wbr/>
+When this is not possible,<wbr/> the bar size should be rounded
+down to the nearest integer and the pattern can repeat
+on the right side.<wbr/></p>
+<p>Each bar's height must always take up the full sensor
+pixel array height.<wbr/></p>
+<p>Each pixel in this test pattern must be set to either
+0% intensity or 100% intensity.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">COLOR_BARS_FADE_TO_GRAY</span>
+                    <span class="entry_type_enum_notes"><p>The test pattern is similar to COLOR_<wbr/>BARS,<wbr/> except that
+each bar should start at its specified color at the top,<wbr/>
+and fade to gray at the bottom.<wbr/></p>
+<p>Furthermore each bar is further subdivided into a left and
+right half.<wbr/> The left half should have a smooth gradient,<wbr/>
+and the right half should have a quantized gradient.<wbr/></p>
+<p>In particular,<wbr/> the right half's should consist of blocks of the
+same color for 1/<wbr/>16th active sensor pixel array width.<wbr/></p>
+<p>The least significant bits in the quantized gradient should
+be copied from the most significant bits of the smooth gradient.<wbr/></p>
+<p>The height of each bar should always be a multiple of 128.<wbr/>
+When this is not the case,<wbr/> the pattern should repeat at the bottom
+of the image.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PN9</span>
+                    <span class="entry_type_enum_notes"><p>All pixel data is replaced by a pseudo-random sequence
+generated from a PN9 512-bit sequence (typically implemented
+in hardware with a linear feedback shift register).<wbr/></p>
+<p>The generator should be reset at the beginning of each frame,<wbr/>
+and thus each subsequent raw frame with this test pattern should
+be exactly the same as the last.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">CUSTOM1</span>
+                    <span class="entry_type_enum_value">256</span>
+                    <span class="entry_type_enum_notes"><p>The first custom test pattern.<wbr/> All custom patterns that are
+available only on this camera device are at least this numeric
+value.<wbr/></p>
+<p>All of the custom test patterns will be static
+(that is the raw image must not vary from frame to frame).<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>When enabled,<wbr/> the sensor sends a test pattern instead of
+doing a real exposure from the camera.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.sensor.availableTestPatternModes">android.<wbr/>sensor.<wbr/>available<wbr/>Test<wbr/>Pattern<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When a test pattern is enabled,<wbr/> all manual sensor controls specified
+by android.<wbr/>sensor.<wbr/>* will be ignored.<wbr/> All other controls should
+work as normal.<wbr/></p>
+<p>For example,<wbr/> if manual flash is enabled,<wbr/> flash firing should still
+occur (and that the test pattern remain unmodified,<wbr/> since the flash
+would not actually affect it).<wbr/></p>
+<p>Defaults to OFF.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>All test patterns are specified in the Bayer domain.<wbr/></p>
+<p>The HAL may choose to substitute test patterns from the sensor
+with test patterns from on-device memory.<wbr/> In that case,<wbr/> it should be
+indistinguishable to the ISP whether the data came from the
+sensor interconnect bus (such as CSI2) or memory.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.rollingShutterSkew">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>rolling<wbr/>Shutter<wbr/>Skew
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Duration between the start of first row exposure
+and the start of last row exposure.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Nanoseconds
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0 and &lt;
+<a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is the exposure time skew between the first and last
+row exposure start times.<wbr/> The first row and the last row are
+the first and last rows inside of the
+<a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+<p>For typical camera sensors that use rolling shutters,<wbr/> this is also equivalent
+to the frame readout time.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The HAL must report <code>0</code> if the sensor is using global shutter,<wbr/> where all pixels begin
+exposure at the same time.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.dynamicBlackLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>dynamic<wbr/>Black<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+                <div class="entry_type_notes">2x2 raw count block</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A per-frame dynamic black level offset for each of the color filter
+arrangement (CFA) mosaic channels.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0 for each.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Camera sensor black levels may vary dramatically for different
+capture settings (e.<wbr/>g.<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>).<wbr/> The fixed black
+level reported by <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may be too
+inaccurate to represent the actual value on a per-frame basis.<wbr/> The
+camera device internal pipeline relies on reliable black level values
+to process the raw images appropriately.<wbr/> To get the best image
+quality,<wbr/> the camera device may choose to estimate the per frame black
+level values either based on optically shielded black regions
+(<a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>) or its internal model.<wbr/></p>
+<p>This key reports the camera device estimated per-frame zero light
+value for each of the CFA mosaic channels in the camera sensor.<wbr/> The
+<a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may only represent a coarse
+approximation of the actual black level values.<wbr/> This value is the
+black level used in camera device internal image processing pipeline
+and generally more accurate than the fixed black level values.<wbr/>
+However,<wbr/> since they are estimated values by the camera device,<wbr/> they
+may not be as accurate as the black level values calculated from the
+optical black pixels reported by <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a>.<wbr/></p>
+<p>The values are given in the same order as channels listed for the CFA
+layout key (see <a href="#static_android.sensor.info.colorFilterArrangement">android.<wbr/>sensor.<wbr/>info.<wbr/>color<wbr/>Filter<wbr/>Arrangement</a>),<wbr/> i.<wbr/>e.<wbr/> the
+nth value given corresponds to the black level offset for the nth
+color channel listed in the CFA.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureResultKeys">CameraCharacteristics#getAvailableCaptureResultKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The values are given in row-column scan order,<wbr/> with the first value
+corresponding to the element of the CFA in row=0,<wbr/> column=0.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.sensor.dynamicWhiteLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sensor.<wbr/>dynamic<wbr/>White<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum raw value output by sensor for this frame.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Since the <a href="#static_android.sensor.blackLevelPattern">android.<wbr/>sensor.<wbr/>black<wbr/>Level<wbr/>Pattern</a> may change for different
+capture settings (e.<wbr/>g.,<wbr/> <a href="#controls_android.sensor.sensitivity">android.<wbr/>sensor.<wbr/>sensitivity</a>),<wbr/> the white
+level will change accordingly.<wbr/> This key is similar to
+<a href="#static_android.sensor.info.whiteLevel">android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level</a>,<wbr/> but specifies the camera device
+estimated white level for each frame.<wbr/></p>
+<p>This key will be available if <a href="#static_android.sensor.opticalBlackRegions">android.<wbr/>sensor.<wbr/>optical<wbr/>Black<wbr/>Regions</a> is
+available or the camera device advertises this key via
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#getAvailableCaptureRequestKeys">CameraCharacteristics#getAvailableCaptureRequestKeys</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The full bit depth of the sensor must be available in the raw data,<wbr/>
+so the value for linear sensors should not be significantly lower
+than maximum raw value supported,<wbr/> i.<wbr/>e.<wbr/> 2^(sensor bits per pixel).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_shading" class="section">shading</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.shading.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>shading.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No lens shading correction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Apply lens shading corrections,<wbr/> without slowing
+frame rate relative to sensor raw output</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Apply high-quality lens shading correction,<wbr/> at the
+cost of possibly reduced frame rate.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Quality of lens shading correction applied
+to the image data.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.shading.availableModes">android.<wbr/>shading.<wbr/>available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to OFF mode,<wbr/> no lens shading correction will be applied by the
+camera device,<wbr/> and an identity lens shading map data will be provided
+if <code><a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> == ON</code>.<wbr/> For example,<wbr/> for lens
+shading map with size of <code>[ 4,<wbr/> 3 ]</code>,<wbr/>
+the output <a href="#dynamic_android.statistics.lensShadingCorrectionMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Correction<wbr/>Map</a> for this case will be an identity
+map shown below:</p>
+<pre><code>[ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0 ]
+</code></pre>
+<p>When set to other modes,<wbr/> lens shading correction will be applied by the camera
+device.<wbr/> Applications can request lens shading map data by setting
+<a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> to ON,<wbr/> and then the camera device will provide lens
+shading map data in <a href="#dynamic_android.statistics.lensShadingCorrectionMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Correction<wbr/>Map</a>; the returned shading map
+data will be the one applied by the camera device for this capture request.<wbr/></p>
+<p>The shading map data may depend on the auto-exposure (AE) and AWB statistics,<wbr/> therefore
+the reliability of the map data may be affected by the AE and AWB algorithms.<wbr/> When AE and
+AWB are in AUTO modes(<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>!=</code> OFF and <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> <code>!=</code>
+OFF),<wbr/> to get best results,<wbr/> it is recommended that the applications wait for the AE and AWB
+to be converged before using the returned shading map data.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.shading.strength">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>shading.<wbr/>strength
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Control the amount of shading correction
+applied to the images</p>
+            </td>
+
+            <td class="entry_units">
+              unitless: 1-10; 10 is full shading
+          compensation
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.shading.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>shading.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>No lens shading correction is applied.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Apply lens shading corrections,<wbr/> without slowing
+frame rate relative to sensor raw output</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>Apply high-quality lens shading correction,<wbr/> at the
+cost of possibly reduced frame rate.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Quality of lens shading correction applied
+to the image data.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.shading.availableModes">android.<wbr/>shading.<wbr/>available<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to OFF mode,<wbr/> no lens shading correction will be applied by the
+camera device,<wbr/> and an identity lens shading map data will be provided
+if <code><a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> == ON</code>.<wbr/> For example,<wbr/> for lens
+shading map with size of <code>[ 4,<wbr/> 3 ]</code>,<wbr/>
+the output <a href="#dynamic_android.statistics.lensShadingCorrectionMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Correction<wbr/>Map</a> for this case will be an identity
+map shown below:</p>
+<pre><code>[ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>
+ 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0 ]
+</code></pre>
+<p>When set to other modes,<wbr/> lens shading correction will be applied by the camera
+device.<wbr/> Applications can request lens shading map data by setting
+<a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> to ON,<wbr/> and then the camera device will provide lens
+shading map data in <a href="#dynamic_android.statistics.lensShadingCorrectionMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Correction<wbr/>Map</a>; the returned shading map
+data will be the one applied by the camera device for this capture request.<wbr/></p>
+<p>The shading map data may depend on the auto-exposure (AE) and AWB statistics,<wbr/> therefore
+the reliability of the map data may be affected by the AE and AWB algorithms.<wbr/> When AE and
+AWB are in AUTO modes(<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>!=</code> OFF and <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> <code>!=</code>
+OFF),<wbr/> to get best results,<wbr/> it is recommended that the applications wait for the AE and AWB
+to be converged before using the returned shading map data.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.shading.availableModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>shading.<wbr/>available<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums (android.<wbr/>shading.<wbr/>mode).<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of lens shading modes for <a href="#controls_android.shading.mode">android.<wbr/>shading.<wbr/>mode</a> that are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.shading.mode">android.<wbr/>shading.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This list contains lens shading modes that can be set for the camera device.<wbr/>
+Camera devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability will always
+list OFF and FAST mode.<wbr/> This includes all FULL level devices.<wbr/>
+LEGACY devices will always only support FAST mode.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if lens shading correction control is
+available on the camera device,<wbr/> but the underlying implementation can be the same for
+both modes.<wbr/> That is,<wbr/> if the highest quality implementation on the camera device does not
+slow down capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_statistics" class="section">statistics</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.statistics.faceDetectMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not include face detection statistics in capture
+results.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SIMPLE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Return face rectangle and confidence values only.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FULL</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Return all face
+metadata.<wbr/></p>
+<p>In this mode,<wbr/> face rectangles,<wbr/> scores,<wbr/> landmarks,<wbr/> and face IDs are all valid.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for the face detector
+unit.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableFaceDetectModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Face<wbr/>Detect<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Whether face detection is enabled,<wbr/> and whether it
+should output just the basic fields or the full set of
+fields.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>SIMPLE mode must fill in <a href="#dynamic_android.statistics.faceRectangles">android.<wbr/>statistics.<wbr/>face<wbr/>Rectangles</a> and
+<a href="#dynamic_android.statistics.faceScores">android.<wbr/>statistics.<wbr/>face<wbr/>Scores</a>.<wbr/>
+FULL mode must also fill in <a href="#dynamic_android.statistics.faceIds">android.<wbr/>statistics.<wbr/>face<wbr/>Ids</a>,<wbr/> and
+<a href="#dynamic_android.statistics.faceLandmarks">android.<wbr/>statistics.<wbr/>face<wbr/>Landmarks</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.statistics.histogramMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>histogram<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for histogram
+generation</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.statistics.sharpnessMapMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>sharpness<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for sharpness map
+generation</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.statistics.hotPixelMapMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel map production is disabled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel map production is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for hot pixel map generation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableHotPixelMapModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If set to <code>true</code>,<wbr/> a hot pixel map is returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/>
+If set to <code>false</code>,<wbr/> no hot pixel map will be returned.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.statistics.lensShadingMapMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not include a lens shading map in the capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Include a lens shading map in the capture result.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will output the lens
+shading map in output result metadata.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableLensShadingMapModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Lens<wbr/>Shading<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to ON,<wbr/>
+<a href="#dynamic_android.statistics.lensShadingMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map</a> will be provided in
+the output result metadata.<wbr/></p>
+<p>ON is always supported on devices with the RAW capability.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+                
+            
+
+                
+          <tr class="entry" id="static_android.statistics.info.availableFaceDetectModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Face<wbr/>Detect<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">List of enums from android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of face detection modes for <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>OFF is always supported.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.histogramBucketCount">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>histogram<wbr/>Bucket<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Number of histogram buckets
+supported</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 64</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.maxFaceCount">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>max<wbr/>Face<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum number of simultaneously detectable
+faces.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>0 for cameras without available face detection; otherwise:
+<code>&gt;=4</code> for LIMITED or FULL hwlevel devices or
+<code>&gt;0</code> for LEGACY devices.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.maxHistogramCount">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>max<wbr/>Histogram<wbr/>Count
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum value possible for a histogram
+bucket</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.maxSharpnessMapValue">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>max<wbr/>Sharpness<wbr/>Map<wbr/>Value
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum value possible for a sharpness map
+region.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.sharpnessMapSize">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>sharpness<wbr/>Map<wbr/>Size
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2
+                </span>
+              <span class="entry_type_visibility"> [system as size]</span>
+
+
+
+
+                <div class="entry_type_notes">width x height</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Dimensions of the sharpness
+map</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Must be at least 32 x 32</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.availableHotPixelMapModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Map<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of hot pixel map output modes for <a href="#controls_android.statistics.hotPixelMapMode">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map<wbr/>Mode</a> that are
+supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.statistics.hotPixelMapMode">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If no hotpixel map output is available for this camera device,<wbr/> this will contain only
+<code>false</code>.<wbr/></p>
+<p>ON is always supported on devices with the RAW capability.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.statistics.info.availableLensShadingMapModes">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Lens<wbr/>Shading<wbr/>Map<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of lens shading map output modes for <a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a> that
+are supported by this camera device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.statistics.lensShadingMapMode">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If no lens shading map output is available for this camera device,<wbr/> this key will
+contain only OFF.<wbr/></p>
+<p>ON is always supported on devices with the RAW capability.<wbr/>
+LEGACY mode devices will always only support OFF.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+        
+
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.statistics.faceDetectMode">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not include face detection statistics in capture
+results.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">SIMPLE</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Return face rectangle and confidence values only.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FULL</span>
+                    <span class="entry_type_enum_optional">[optional]</span>
+                    <span class="entry_type_enum_notes"><p>Return all face
+metadata.<wbr/></p>
+<p>In this mode,<wbr/> face rectangles,<wbr/> scores,<wbr/> landmarks,<wbr/> and face IDs are all valid.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for the face detector
+unit.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableFaceDetectModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Face<wbr/>Detect<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Whether face detection is enabled,<wbr/> and whether it
+should output just the basic fields or the full set of
+fields.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>SIMPLE mode must fill in <a href="#dynamic_android.statistics.faceRectangles">android.<wbr/>statistics.<wbr/>face<wbr/>Rectangles</a> and
+<a href="#dynamic_android.statistics.faceScores">android.<wbr/>statistics.<wbr/>face<wbr/>Scores</a>.<wbr/>
+FULL mode must also fill in <a href="#dynamic_android.statistics.faceIds">android.<wbr/>statistics.<wbr/>face<wbr/>Ids</a>,<wbr/> and
+<a href="#dynamic_android.statistics.faceLandmarks">android.<wbr/>statistics.<wbr/>face<wbr/>Landmarks</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.faceIds">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Ids
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of unique IDs for detected faces.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Each detected face is given a unique ID that is valid for as long as the face is visible
+to the camera device.<wbr/>  A face that leaves the field of view and later returns may be
+assigned a new ID.<wbr/></p>
+<p>Only available if <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> == FULL</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.faceLandmarks">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Landmarks
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 6
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">(leftEyeX,<wbr/> leftEyeY,<wbr/> rightEyeX,<wbr/> rightEyeY,<wbr/> mouthX,<wbr/> mouthY)</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of landmarks for detected
+faces.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The coordinate system is that of <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>,<wbr/> with
+<code>(0,<wbr/> 0)</code> being the top-left pixel of the active array.<wbr/></p>
+<p>Only available if <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> == FULL</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.faceRectangles">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Rectangles
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 4
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as rectangle]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+                <div class="entry_type_notes">(xmin,<wbr/> ymin,<wbr/> xmax,<wbr/> ymax).<wbr/> (0,<wbr/>0) is top-left of active pixel area</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of the bounding rectangles for detected
+faces.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The coordinate system is that of <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>,<wbr/> with
+<code>(0,<wbr/> 0)</code> being the top-left pixel of the active array.<wbr/></p>
+<p>Only available if <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> != OFF</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.faceScores">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>statistics.<wbr/>face<wbr/>Scores
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of the face confidence scores for
+detected faces</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>1-100</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_BC">BC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only available if <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> != OFF.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The value should be meaningful (for example,<wbr/> setting 100 at
+all times is illegal).<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.faces">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>faces
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [java_public as face]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of the faces detected through camera face detection
+in this capture.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Only available if <a href="#controls_android.statistics.faceDetectMode">android.<wbr/>statistics.<wbr/>face<wbr/>Detect<wbr/>Mode</a> <code>!=</code> OFF.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.histogram">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>histogram
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+                <div class="entry_type_notes">count of pixels for each color channel that fall into each histogram bucket,<wbr/> scaled to be between 0 and maxHistogramCount</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A 3-channel histogram based on the raw
+sensor data</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The k'th bucket (0-based) covers the input range
+(with w = <a href="#static_android.sensor.info.whiteLevel">android.<wbr/>sensor.<wbr/>info.<wbr/>white<wbr/>Level</a>) of [ k * w/<wbr/>N,<wbr/>
+(k + 1) * w /<wbr/> N ).<wbr/> If only a monochrome sharpness map is
+supported,<wbr/> all channels should have the same data</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.histogramMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>histogram<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for histogram
+generation</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.sharpnessMap">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>sharpness<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x m x 3
+                </span>
+              <span class="entry_type_visibility"> [system]</span>
+
+
+
+
+                <div class="entry_type_notes">estimated sharpness for each region of the input image.<wbr/> Normalized to be between 0 and maxSharpnessMapValue.<wbr/> Higher values mean sharper (better focused)</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A 3-channel sharpness map,<wbr/> based on the raw
+sensor data</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If only a monochrome sharpness map is supported,<wbr/>
+all channels should have the same data</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.sharpnessMapMode">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>statistics.<wbr/>sharpness<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [system as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for sharpness map
+generation</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_FUTURE">FUTURE</a></li>
+              </ul>
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.lensShadingCorrectionMap">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Correction<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+
+              <span class="entry_type_visibility"> [java_public as lensShadingMap]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The shading map is a low-resolution floating-point map
+that lists the coefficients used to correct for vignetting,<wbr/> for each
+Bayer color channel.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Each gain factor is &gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The map provided here is the same map that is used by the camera device to
+correct both color shading and vignetting for output non-RAW images.<wbr/></p>
+<p>When there is no lens shading correction applied to RAW
+output images (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code>
+false),<wbr/> this map is the complete lens shading correction
+map; when there is some lens shading correction applied to
+the RAW output image (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a><code>==</code> true),<wbr/> this map reports the remaining lens shading
+correction map that needs to be applied to get shading
+corrected images that match the camera device's output for
+non-RAW formats.<wbr/></p>
+<p>For a complete shading correction map,<wbr/> the least shaded
+section of the image will have a gain factor of 1; all
+other sections will have gains above 1.<wbr/></p>
+<p>When <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> = TRANSFORM_<wbr/>MATRIX,<wbr/> the map
+will take into account the colorCorrection settings.<wbr/></p>
+<p>The shading map is for the entire active pixel array,<wbr/> and is not
+affected by the crop region specified in the request.<wbr/> Each shading map
+entry is the value of the shading compensation map over a specific
+pixel on the sensor.<wbr/>  Specifically,<wbr/> with a (N x M) resolution shading
+map,<wbr/> and an active pixel array size (W x H),<wbr/> shading map entry
+(x,<wbr/>y) ϵ (0 ...<wbr/> N-1,<wbr/> 0 ...<wbr/> M-1) is the value of the shading map at
+pixel ( ((W-1)/<wbr/>(N-1)) * x,<wbr/> ((H-1)/<wbr/>(M-1)) * y) for the four color channels.<wbr/>
+The map is assumed to be bilinearly interpolated between the sample points.<wbr/></p>
+<p>The channel order is [R,<wbr/> Geven,<wbr/> Godd,<wbr/> B],<wbr/> where Geven is the green
+channel for the even rows of a Bayer pattern,<wbr/> and Godd is the odd rows.<wbr/>
+The shading map is stored in a fully interleaved format.<wbr/></p>
+<p>The shading map will generally have on the order of 30-40 rows and columns,<wbr/>
+and will be smaller than 64x64.<wbr/></p>
+<p>As an example,<wbr/> given a very small map defined as:</p>
+<pre><code>width,<wbr/>height = [ 4,<wbr/> 3 ]
+values =
+[ 1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/>
+    1.<wbr/>1,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/> 1.<wbr/>3,<wbr/>
+  1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>25,<wbr/> 1.<wbr/>1,<wbr/>  1.<wbr/>1,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>0,<wbr/>
+    1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/> 1.<wbr/>25,<wbr/> 1.<wbr/>2,<wbr/>
+  1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/>   1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>2,<wbr/>
+    1.<wbr/>2,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>3,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3 ]
+</code></pre>
+<p>The low-resolution scaling map images for each channel are
+(displayed using nearest-neighbor interpolation):</p>
+<p><img alt="Red lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png"/>
+<img alt="Green (even rows) lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png"/>
+<img alt="Green (odd rows) lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png"/>
+<img alt="Blue lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png"/></p>
+<p>As a visualization only,<wbr/> inverting the full-color map to recover an
+image of a gray wall (using bicubic interpolation for visual quality) as captured by the sensor gives:</p>
+<p><img alt="Image of a uniform white wall (inverse shading map)" src="images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png"/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.lensShadingMap">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x n x m
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">2D array of float gain factors per channel to correct lens shading</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The shading map is a low-resolution floating-point map
+that lists the coefficients used to correct for vignetting and color shading,<wbr/>
+for each Bayer color channel of RAW image data.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Each gain factor is &gt;= 1</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The map provided here is the same map that is used by the camera device to
+correct both color shading and vignetting for output non-RAW images.<wbr/></p>
+<p>When there is no lens shading correction applied to RAW
+output images (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> <code>==</code>
+false),<wbr/> this map is the complete lens shading correction
+map; when there is some lens shading correction applied to
+the RAW output image (<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a><code>==</code> true),<wbr/> this map reports the remaining lens shading
+correction map that needs to be applied to get shading
+corrected images that match the camera device's output for
+non-RAW formats.<wbr/></p>
+<p>For a complete shading correction map,<wbr/> the least shaded
+section of the image will have a gain factor of 1; all
+other sections will have gains above 1.<wbr/></p>
+<p>When <a href="#controls_android.colorCorrection.mode">android.<wbr/>color<wbr/>Correction.<wbr/>mode</a> = TRANSFORM_<wbr/>MATRIX,<wbr/> the map
+will take into account the colorCorrection settings.<wbr/></p>
+<p>The shading map is for the entire active pixel array,<wbr/> and is not
+affected by the crop region specified in the request.<wbr/> Each shading map
+entry is the value of the shading compensation map over a specific
+pixel on the sensor.<wbr/>  Specifically,<wbr/> with a (N x M) resolution shading
+map,<wbr/> and an active pixel array size (W x H),<wbr/> shading map entry
+(x,<wbr/>y) ϵ (0 ...<wbr/> N-1,<wbr/> 0 ...<wbr/> M-1) is the value of the shading map at
+pixel ( ((W-1)/<wbr/>(N-1)) * x,<wbr/> ((H-1)/<wbr/>(M-1)) * y) for the four color channels.<wbr/>
+The map is assumed to be bilinearly interpolated between the sample points.<wbr/></p>
+<p>The channel order is [R,<wbr/> Geven,<wbr/> Godd,<wbr/> B],<wbr/> where Geven is the green
+channel for the even rows of a Bayer pattern,<wbr/> and Godd is the odd rows.<wbr/>
+The shading map is stored in a fully interleaved format,<wbr/> and its size
+is provided in the camera static metadata by <a href="#static_android.lens.info.shadingMapSize">android.<wbr/>lens.<wbr/>info.<wbr/>shading<wbr/>Map<wbr/>Size</a>.<wbr/></p>
+<p>The shading map will generally have on the order of 30-40 rows and columns,<wbr/>
+and will be smaller than 64x64.<wbr/></p>
+<p>As an example,<wbr/> given a very small map defined as:</p>
+<pre><code><a href="#static_android.lens.info.shadingMapSize">android.<wbr/>lens.<wbr/>info.<wbr/>shading<wbr/>Map<wbr/>Size</a> = [ 4,<wbr/> 3 ]
+<a href="#dynamic_android.statistics.lensShadingMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map</a> =
+[ 1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/>
+    1.<wbr/>1,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/> 1.<wbr/>3,<wbr/>
+  1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>25,<wbr/> 1.<wbr/>1,<wbr/>  1.<wbr/>1,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>0,<wbr/>
+    1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/>  1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/> 1.<wbr/>25,<wbr/> 1.<wbr/>2,<wbr/>
+  1.<wbr/>3,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3,<wbr/>   1.<wbr/>2,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>2,<wbr/>
+    1.<wbr/>2,<wbr/> 1.<wbr/>1,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>2,<wbr/>  1.<wbr/>3,<wbr/> 1.<wbr/>15,<wbr/> 1.<wbr/>2,<wbr/> 1.<wbr/>3 ]
+</code></pre>
+<p>The low-resolution scaling map images for each channel are
+(displayed using nearest-neighbor interpolation):</p>
+<p><img alt="Red lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/red_shading.png"/>
+<img alt="Green (even rows) lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/green_e_shading.png"/>
+<img alt="Green (odd rows) lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/green_o_shading.png"/>
+<img alt="Blue lens shading map" src="images/camera2/metadata/android.statistics.lensShadingMap/blue_shading.png"/></p>
+<p>As a visualization only,<wbr/> inverting the full-color map to recover an
+image of a gray wall (using bicubic interpolation for visual quality)
+as captured by the sensor gives:</p>
+<p><img alt="Image of a uniform white wall (inverse shading map)" src="images/camera2/metadata/android.statistics.lensShadingMap/inv_shading.png"/></p>
+<p>Note that the RAW image data might be subject to lens shading
+correction not reported on this map.<wbr/> Query
+<a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a> to see if RAW image data has subject
+to lens shading correction.<wbr/> If <a href="#static_android.sensor.info.lensShadingApplied">android.<wbr/>sensor.<wbr/>info.<wbr/>lens<wbr/>Shading<wbr/>Applied</a>
+is TRUE,<wbr/> the RAW image data is subject to partial or full lens shading
+correction.<wbr/> In the case full lens shading correction is applied to RAW
+images,<wbr/> the gain factor map reported in this key will contain all 1.<wbr/>0 gains.<wbr/>
+In other words,<wbr/> the map reported in this key is the remaining lens shading
+that needs to be applied on the RAW image to get images without lens shading
+artifacts.<wbr/> See <a href="#static_android.request.maxNumOutputRaw">android.<wbr/>request.<wbr/>max<wbr/>Num<wbr/>Output<wbr/>Raw</a> for a list of RAW image
+formats.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The lens shading map calculation may depend on exposure and white balance statistics.<wbr/>
+When AE and AWB are in AUTO modes
+(<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>!=</code> OFF and <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> <code>!=</code> OFF),<wbr/> the HAL
+may have all the information it need to generate most accurate lens shading map.<wbr/> When
+AE or AWB are in manual mode
+(<a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> <code>==</code> OFF or <a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a> <code>==</code> OFF),<wbr/> the shading map
+may be adversely impacted by manual exposure or white balance parameters.<wbr/> To avoid
+generating unreliable shading map data,<wbr/> the HAL may choose to lock the shading map with
+the latest known good map generated when the AE and AWB are in AUTO modes.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.predictedColorGains">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>predicted<wbr/>Color<wbr/>Gains
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4
+                </span>
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+                <div class="entry_type_notes">A 1D array of floats for 4 color channel gains</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The best-fit color channel gains calculated
+by the camera device's statistics units for the current output frame.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This may be different than the gains used for this frame,<wbr/>
+since statistics processing on data from a new frame
+typically completes after the transform has already been
+applied to that frame.<wbr/></p>
+<p>The 4 channel gains are defined in Bayer domain,<wbr/>
+see <a href="#controls_android.colorCorrection.gains">android.<wbr/>color<wbr/>Correction.<wbr/>gains</a> for details.<wbr/></p>
+<p>This value should always be calculated by the auto-white balance (AWB) block,<wbr/>
+regardless of the android.<wbr/>control.<wbr/>* current values.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.predictedColorTransform">
+            <td class="entry_name
+                entry_name_deprecated
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>predicted<wbr/>Color<wbr/>Transform
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">rational</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  3 x 3
+                </span>
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+              <span class="entry_type_deprecated">[deprecated] </span>
+
+                <div class="entry_type_notes">3x3 rational matrix in row-major order</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The best-fit color transform matrix estimate
+calculated by the camera device's statistics units for the current
+output frame.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><span class="entry_range_deprecated">Deprecated</span>. Do not use.</p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The camera device will provide the estimate from its
+statistics unit on the white balance transforms to use
+for the next frame.<wbr/> These are the values the camera device believes
+are the best fit for the current output frame.<wbr/> This may
+be different than the transform used for this frame,<wbr/> since
+statistics processing on data from a new frame typically
+completes after the transform has already been applied to
+that frame.<wbr/></p>
+<p>These estimates must be provided for all frames,<wbr/> even if
+capture settings and color transforms are set by the application.<wbr/></p>
+<p>This value should always be calculated by the auto-white balance (AWB) block,<wbr/>
+regardless of the android.<wbr/>control.<wbr/>* current values.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.sceneFlicker">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>scene<wbr/>Flicker
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">NONE</span>
+                    <span class="entry_type_enum_notes"><p>The camera device does not detect any flickering illumination
+in the current scene.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">50HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device detects illumination flickering at 50Hz
+in the current scene.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">60HZ</span>
+                    <span class="entry_type_enum_notes"><p>The camera device detects illumination flickering at 60Hz
+in the current scene.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The camera device estimated scene illumination lighting
+frequency.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Many light sources,<wbr/> such as most fluorescent lights,<wbr/> flicker at a rate
+that depends on the local utility power standards.<wbr/> This flicker must be
+accounted for by auto-exposure routines to avoid artifacts in captured images.<wbr/>
+The camera device uses this entry to tell the application what the scene
+illuminant frequency is.<wbr/></p>
+<p>When manual exposure control is enabled
+(<code><a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a> == OFF</code> or <code><a href="#controls_android.control.mode">android.<wbr/>control.<wbr/>mode</a> ==
+OFF</code>),<wbr/> the <a href="#controls_android.control.aeAntibandingMode">android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode</a> doesn't perform
+antibanding,<wbr/> and the application can ensure it selects
+exposure times that do not cause banding issues by looking
+into this metadata field.<wbr/> See
+<a href="#controls_android.control.aeAntibandingMode">android.<wbr/>control.<wbr/>ae<wbr/>Antibanding<wbr/>Mode</a> for more details.<wbr/></p>
+<p>Reports NONE if there doesn't appear to be flickering illumination.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.hotPixelMapMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel map production is disabled.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Hot pixel map production is enabled.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Operating mode for hot pixel map generation.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableHotPixelMapModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Hot<wbr/>Pixel<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If set to <code>true</code>,<wbr/> a hot pixel map is returned in <a href="#dynamic_android.statistics.hotPixelMap">android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map</a>.<wbr/>
+If set to <code>false</code>,<wbr/> no hot pixel map will be returned.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.hotPixelMap">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>statistics.<wbr/>hot<wbr/>Pixel<wbr/>Map
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  2 x n
+                </span>
+              <span class="entry_type_visibility"> [public as point]</span>
+
+
+
+
+                <div class="entry_type_notes">list of coordinates based on android.<wbr/>sensor.<wbr/>pixel<wbr/>Array<wbr/>Size</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of <code>(x,<wbr/> y)</code> coordinates of hot/<wbr/>defective pixels on the sensor.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>n &lt;= number of pixels on the sensor.<wbr/>
+The <code>(x,<wbr/> y)</code> coordinates must be bounded by
+<a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A coordinate <code>(x,<wbr/> y)</code> must lie between <code>(0,<wbr/> 0)</code>,<wbr/> and
+<code>(width - 1,<wbr/> height - 1)</code> (inclusive),<wbr/> which are the top-left and
+bottom-right of the pixel array,<wbr/> respectively.<wbr/> The width and
+height dimensions are given in <a href="#static_android.sensor.info.pixelArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>pixel<wbr/>Array<wbr/>Size</a>.<wbr/>
+This may include hot pixels that lie outside of the active array
+bounds given by <a href="#static_android.sensor.info.activeArraySize">android.<wbr/>sensor.<wbr/>info.<wbr/>active<wbr/>Array<wbr/>Size</a>.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A hotpixel map contains the coordinates of pixels on the camera
+sensor that do report valid values (usually due to defects in
+the camera sensor).<wbr/> This includes pixels that are stuck at certain
+values,<wbr/> or have a response that does not accuractly encode the
+incoming light from the scene.<wbr/></p>
+<p>To avoid performance issues,<wbr/> there should be significantly fewer hot
+pixels than actual pixels on the camera sensor.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.statistics.lensShadingMapMode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map<wbr/>Mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                    <span class="entry_type_enum_notes"><p>Do not include a lens shading map in the capture result.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                    <span class="entry_type_enum_notes"><p>Include a lens shading map in the capture result.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether the camera device will output the lens
+shading map in output result metadata.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.statistics.info.availableLensShadingMapModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Lens<wbr/>Shading<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_RAW">RAW</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to ON,<wbr/>
+<a href="#dynamic_android.statistics.lensShadingMap">android.<wbr/>statistics.<wbr/>lens<wbr/>Shading<wbr/>Map</a> will be provided in
+the output result metadata.<wbr/></p>
+<p>ON is always supported on devices with the RAW capability.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_tonemap" class="section">tonemap</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.tonemap.curveBlue">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Blue
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the blue
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>See <a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> for more details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.curveGreen">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Green
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the green
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>See <a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> for more details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.curveRed">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Red
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the red
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>0-1 on both input and output coordinates,<wbr/> normalized
+as a floating-point value such that 0 == black and 1 == white.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Each channel's curve is defined by an array of control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> =
+  [ P0in,<wbr/> P0out,<wbr/> P1in,<wbr/> P1out,<wbr/> P2in,<wbr/> P2out,<wbr/> P3in,<wbr/> P3out,<wbr/> ...,<wbr/> PNin,<wbr/> PNout ]
+2 &lt;= N &lt;= <a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a></code></pre>
+<p>These are sorted in order of increasing <code>Pin</code>; it is
+required that input values 0.<wbr/>0 and 1.<wbr/>0 are included in the list to
+define a complete mapping.<wbr/> For input values between control points,<wbr/>
+the camera device must linearly interpolate between the control
+points.<wbr/></p>
+<p>Each curve can have an independent number of points,<wbr/> and the number
+of points can be less than max (that is,<wbr/> the request doesn't have to
+always provide a curve with number of points equivalent to
+<a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a>).<wbr/></p>
+<p>A few examples,<wbr/> and their corresponding graphical mappings; these
+only specify the red channel and the precision is limited to 4
+digits,<wbr/> for conciseness.<wbr/></p>
+<p>Linear mapping:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [ 0,<wbr/> 0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0 ]
+</code></pre>
+<p><img alt="Linear mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png"/></p>
+<p>Invert mapping:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [ 0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 0 ]
+</code></pre>
+<p><img alt="Inverting mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png"/></p>
+<p>Gamma 1/<wbr/>2.<wbr/>2 mapping,<wbr/> with 16 control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [
+  0.<wbr/>0000,<wbr/> 0.<wbr/>0000,<wbr/> 0.<wbr/>0667,<wbr/> 0.<wbr/>2920,<wbr/> 0.<wbr/>1333,<wbr/> 0.<wbr/>4002,<wbr/> 0.<wbr/>2000,<wbr/> 0.<wbr/>4812,<wbr/>
+  0.<wbr/>2667,<wbr/> 0.<wbr/>5484,<wbr/> 0.<wbr/>3333,<wbr/> 0.<wbr/>6069,<wbr/> 0.<wbr/>4000,<wbr/> 0.<wbr/>6594,<wbr/> 0.<wbr/>4667,<wbr/> 0.<wbr/>7072,<wbr/>
+  0.<wbr/>5333,<wbr/> 0.<wbr/>7515,<wbr/> 0.<wbr/>6000,<wbr/> 0.<wbr/>7928,<wbr/> 0.<wbr/>6667,<wbr/> 0.<wbr/>8317,<wbr/> 0.<wbr/>7333,<wbr/> 0.<wbr/>8685,<wbr/>
+  0.<wbr/>8000,<wbr/> 0.<wbr/>9035,<wbr/> 0.<wbr/>8667,<wbr/> 0.<wbr/>9370,<wbr/> 0.<wbr/>9333,<wbr/> 0.<wbr/>9691,<wbr/> 1.<wbr/>0000,<wbr/> 1.<wbr/>0000 ]
+</code></pre>
+<p><img alt="Gamma = 1/2.2 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png"/></p>
+<p>Standard sRGB gamma mapping,<wbr/> per IEC 61966-2-1:1999,<wbr/> with 16 control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [
+  0.<wbr/>0000,<wbr/> 0.<wbr/>0000,<wbr/> 0.<wbr/>0667,<wbr/> 0.<wbr/>2864,<wbr/> 0.<wbr/>1333,<wbr/> 0.<wbr/>4007,<wbr/> 0.<wbr/>2000,<wbr/> 0.<wbr/>4845,<wbr/>
+  0.<wbr/>2667,<wbr/> 0.<wbr/>5532,<wbr/> 0.<wbr/>3333,<wbr/> 0.<wbr/>6125,<wbr/> 0.<wbr/>4000,<wbr/> 0.<wbr/>6652,<wbr/> 0.<wbr/>4667,<wbr/> 0.<wbr/>7130,<wbr/>
+  0.<wbr/>5333,<wbr/> 0.<wbr/>7569,<wbr/> 0.<wbr/>6000,<wbr/> 0.<wbr/>7977,<wbr/> 0.<wbr/>6667,<wbr/> 0.<wbr/>8360,<wbr/> 0.<wbr/>7333,<wbr/> 0.<wbr/>8721,<wbr/>
+  0.<wbr/>8000,<wbr/> 0.<wbr/>9063,<wbr/> 0.<wbr/>8667,<wbr/> 0.<wbr/>9389,<wbr/> 0.<wbr/>9333,<wbr/> 0.<wbr/>9701,<wbr/> 1.<wbr/>0000,<wbr/> 1.<wbr/>0000 ]
+</code></pre>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For good quality of mapping,<wbr/> at least 128 control points are
+preferred.<wbr/></p>
+<p>A typical use case of this would be a gamma-1/<wbr/>2.<wbr/>2 curve,<wbr/> with as many
+control points used as are available.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.curve">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>curve
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a>
+is CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemapCurve consist of three curves for each of red,<wbr/> green,<wbr/> and blue
+channels respectively.<wbr/> The following example uses the red channel as an
+example.<wbr/> The same logic applies to green and blue channel.<wbr/>
+Each channel's curve is defined by an array of control points:</p>
+<pre><code>curveRed =
+  [ P0(in,<wbr/> out),<wbr/> P1(in,<wbr/> out),<wbr/> P2(in,<wbr/> out),<wbr/> P3(in,<wbr/> out),<wbr/> ...,<wbr/> PN(in,<wbr/> out) ]
+2 &lt;= N &lt;= <a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a></code></pre>
+<p>These are sorted in order of increasing <code>Pin</code>; it is always
+guaranteed that input values 0.<wbr/>0 and 1.<wbr/>0 are included in the list to
+define a complete mapping.<wbr/> For input values between control points,<wbr/>
+the camera device must linearly interpolate between the control
+points.<wbr/></p>
+<p>Each curve can have an independent number of points,<wbr/> and the number
+of points can be less than max (that is,<wbr/> the request doesn't have to
+always provide a curve with number of points equivalent to
+<a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a>).<wbr/></p>
+<p>A few examples,<wbr/> and their corresponding graphical mappings; these
+only specify the red channel and the precision is limited to 4
+digits,<wbr/> for conciseness.<wbr/></p>
+<p>Linear mapping:</p>
+<pre><code>curveRed = [ (0,<wbr/> 0),<wbr/> (1.<wbr/>0,<wbr/> 1.<wbr/>0) ]
+</code></pre>
+<p><img alt="Linear mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png"/></p>
+<p>Invert mapping:</p>
+<pre><code>curveRed = [ (0,<wbr/> 1.<wbr/>0),<wbr/> (1.<wbr/>0,<wbr/> 0) ]
+</code></pre>
+<p><img alt="Inverting mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png"/></p>
+<p>Gamma 1/<wbr/>2.<wbr/>2 mapping,<wbr/> with 16 control points:</p>
+<pre><code>curveRed = [
+  (0.<wbr/>0000,<wbr/> 0.<wbr/>0000),<wbr/> (0.<wbr/>0667,<wbr/> 0.<wbr/>2920),<wbr/> (0.<wbr/>1333,<wbr/> 0.<wbr/>4002),<wbr/> (0.<wbr/>2000,<wbr/> 0.<wbr/>4812),<wbr/>
+  (0.<wbr/>2667,<wbr/> 0.<wbr/>5484),<wbr/> (0.<wbr/>3333,<wbr/> 0.<wbr/>6069),<wbr/> (0.<wbr/>4000,<wbr/> 0.<wbr/>6594),<wbr/> (0.<wbr/>4667,<wbr/> 0.<wbr/>7072),<wbr/>
+  (0.<wbr/>5333,<wbr/> 0.<wbr/>7515),<wbr/> (0.<wbr/>6000,<wbr/> 0.<wbr/>7928),<wbr/> (0.<wbr/>6667,<wbr/> 0.<wbr/>8317),<wbr/> (0.<wbr/>7333,<wbr/> 0.<wbr/>8685),<wbr/>
+  (0.<wbr/>8000,<wbr/> 0.<wbr/>9035),<wbr/> (0.<wbr/>8667,<wbr/> 0.<wbr/>9370),<wbr/> (0.<wbr/>9333,<wbr/> 0.<wbr/>9691),<wbr/> (1.<wbr/>0000,<wbr/> 1.<wbr/>0000) ]
+</code></pre>
+<p><img alt="Gamma = 1/2.2 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png"/></p>
+<p>Standard sRGB gamma mapping,<wbr/> per IEC 61966-2-1:1999,<wbr/> with 16 control points:</p>
+<pre><code>curveRed = [
+  (0.<wbr/>0000,<wbr/> 0.<wbr/>0000),<wbr/> (0.<wbr/>0667,<wbr/> 0.<wbr/>2864),<wbr/> (0.<wbr/>1333,<wbr/> 0.<wbr/>4007),<wbr/> (0.<wbr/>2000,<wbr/> 0.<wbr/>4845),<wbr/>
+  (0.<wbr/>2667,<wbr/> 0.<wbr/>5532),<wbr/> (0.<wbr/>3333,<wbr/> 0.<wbr/>6125),<wbr/> (0.<wbr/>4000,<wbr/> 0.<wbr/>6652),<wbr/> (0.<wbr/>4667,<wbr/> 0.<wbr/>7130),<wbr/>
+  (0.<wbr/>5333,<wbr/> 0.<wbr/>7569),<wbr/> (0.<wbr/>6000,<wbr/> 0.<wbr/>7977),<wbr/> (0.<wbr/>6667,<wbr/> 0.<wbr/>8360),<wbr/> (0.<wbr/>7333,<wbr/> 0.<wbr/>8721),<wbr/>
+  (0.<wbr/>8000,<wbr/> 0.<wbr/>9063),<wbr/> (0.<wbr/>8667,<wbr/> 0.<wbr/>9389),<wbr/> (0.<wbr/>9333,<wbr/> 0.<wbr/>9701),<wbr/> (1.<wbr/>0000,<wbr/> 1.<wbr/>0000) ]
+</code></pre>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is created by the framework from the curveRed,<wbr/> curveGreen and
+curveBlue entries.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CONTRAST_CURVE</span>
+                    <span class="entry_type_enum_notes"><p>Use the tone mapping curve specified in
+the <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>* entries.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by
+<a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw
+sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Advanced gamma mapping and color enhancement may be applied,<wbr/> without
+reducing frame rate compared to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality gamma mapping and color enhancement will be applied,<wbr/> at
+the cost of possibly reduced frame rate compared to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">GAMMA_VALUE</span>
+                    <span class="entry_type_enum_notes"><p>Use the gamma value specified in <a href="#controls_android.tonemap.gamma">android.<wbr/>tonemap.<wbr/>gamma</a> to peform
+tonemapping.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by <a href="#controls_android.tonemap.gamma">android.<wbr/>tonemap.<wbr/>gamma</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PRESET_CURVE</span>
+                    <span class="entry_type_enum_notes"><p>Use the preset tonemapping curve specified in
+<a href="#controls_android.tonemap.presetCurve">android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve</a> to peform tonemapping.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by
+<a href="#controls_android.tonemap.presetCurve">android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw sensor output.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>High-level global contrast/<wbr/>gamma/<wbr/>tonemapping control.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.tonemap.availableToneMapModes">android.<wbr/>tonemap.<wbr/>available<wbr/>Tone<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When switching to an application-defined contrast curve by setting
+<a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> to CONTRAST_<wbr/>CURVE,<wbr/> the curve is defined
+per-channel with a set of <code>(in,<wbr/> out)</code> points that specify the
+mapping from input high-bit-depth pixel value to the output
+low-bit-depth value.<wbr/>  Since the actual pixel ranges of both input
+and output may change depending on the camera pipeline,<wbr/> the values
+are specified by normalized floating-point numbers.<wbr/></p>
+<p>More-complex color mapping operations such as 3D color look-up
+tables,<wbr/> selective chroma enhancement,<wbr/> or other non-linear color
+transforms will be disabled when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+<p>When using either FAST or HIGH_<wbr/>QUALITY,<wbr/> the camera device will
+emit its own tonemap curve in <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>.<wbr/>
+These values are always available,<wbr/> and as close as possible to the
+actually used nonlinear/<wbr/>nonglobal transforms.<wbr/></p>
+<p>If a request is sent with CONTRAST_<wbr/>CURVE with the camera device's
+provided curve in FAST or HIGH_<wbr/>QUALITY,<wbr/> the image's tonemap will be
+roughly the same.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.gamma">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>gamma
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+GAMMA_<wbr/>VALUE</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemap curve will be defined the following formula:
+* OUT = pow(IN,<wbr/> 1.<wbr/>0 /<wbr/> gamma)
+where IN and OUT is the input pixel value scaled to range [0.<wbr/>0,<wbr/> 1.<wbr/>0],<wbr/>
+pow is the power function and gamma is the gamma value specified by this
+key.<wbr/></p>
+<p>The same curve will be applied to all color channels.<wbr/> The camera device
+may clip the input gamma value to its supported range.<wbr/> The actual applied
+value will be returned in capture result.<wbr/></p>
+<p>The valid range of gamma value varies on different devices,<wbr/> but values
+within [1.<wbr/>0,<wbr/> 5.<wbr/>0] are guaranteed not to be clipped.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="controls_android.tonemap.presetCurve">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">SRGB</span>
+                    <span class="entry_type_enum_notes"><p>Tonemapping curve is defined by sRGB</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">REC709</span>
+                    <span class="entry_type_enum_notes"><p>Tonemapping curve is defined by ITU-R BT.<wbr/>709</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+PRESET_<wbr/>CURVE</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemap curve will be defined by specified standard.<wbr/></p>
+<p>sRGB (approximated by 16 control points):</p>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+<p>Rec.<wbr/> 709 (approximated by 16 control points):</p>
+<p><img alt="Rec. 709 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png"/></p>
+<p>Note that above figures show a 16 control points approximation of preset
+curves.<wbr/> Camera devices may apply a different approximation to the curve.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.tonemap.maxCurvePoints">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum number of supported points in the
+tonemap curve that can be used for <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If the actual number of points provided by the application (in <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>*) is
+less than this maximum,<wbr/> the camera device will resample the curve to its internal
+representation,<wbr/> using linear interpolation.<wbr/></p>
+<p>The output curves in the result metadata may have a different number
+of points than the input curves,<wbr/> and will represent the actual
+hardware curves used as closely as possible when linearly interpolated.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This value must be at least 64.<wbr/> This should be at least 128.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.tonemap.availableToneMapModes">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>available<wbr/>Tone<wbr/>Map<wbr/>Modes
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [public as enumList]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">list of enums</div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>List of tonemapping modes for <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> that are supported by this camera
+device.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Any value listed in <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Camera devices that support the MANUAL_<wbr/>POST_<wbr/>PROCESSING capability will always contain
+at least one of below mode combinations:</p>
+<ul>
+<li>CONTRAST_<wbr/>CURVE,<wbr/> FAST and HIGH_<wbr/>QUALITY</li>
+<li>GAMMA_<wbr/>VALUE,<wbr/> PRESET_<wbr/>CURVE,<wbr/> FAST and HIGH_<wbr/>QUALITY</li>
+</ul>
+<p>This includes all FULL level devices.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>HAL must support both FAST and HIGH_<wbr/>QUALITY if automatic tonemap control is available
+on the camera device,<wbr/> but the underlying implementation can be the same for both modes.<wbr/>
+That is,<wbr/> if the highest quality implementation on the camera device does not slow down
+capture rate,<wbr/> then FAST and HIGH_<wbr/>QUALITY will generate the same output.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.tonemap.curveBlue">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Blue
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the blue
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>See <a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> for more details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.curveGreen">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Green
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the green
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>See <a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> for more details.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.curveRed">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>curve<wbr/>Red
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 2
+                </span>
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+                <div class="entry_type_notes">1D array of float pairs (P_<wbr/>IN,<wbr/> P_<wbr/>OUT).<wbr/> The maximum number of pairs is specified by android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points.<wbr/></div>
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve for the red
+channel,<wbr/> to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>0-1 on both input and output coordinates,<wbr/> normalized
+as a floating-point value such that 0 == black and 1 == white.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Each channel's curve is defined by an array of control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> =
+  [ P0in,<wbr/> P0out,<wbr/> P1in,<wbr/> P1out,<wbr/> P2in,<wbr/> P2out,<wbr/> P3in,<wbr/> P3out,<wbr/> ...,<wbr/> PNin,<wbr/> PNout ]
+2 &lt;= N &lt;= <a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a></code></pre>
+<p>These are sorted in order of increasing <code>Pin</code>; it is
+required that input values 0.<wbr/>0 and 1.<wbr/>0 are included in the list to
+define a complete mapping.<wbr/> For input values between control points,<wbr/>
+the camera device must linearly interpolate between the control
+points.<wbr/></p>
+<p>Each curve can have an independent number of points,<wbr/> and the number
+of points can be less than max (that is,<wbr/> the request doesn't have to
+always provide a curve with number of points equivalent to
+<a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a>).<wbr/></p>
+<p>A few examples,<wbr/> and their corresponding graphical mappings; these
+only specify the red channel and the precision is limited to 4
+digits,<wbr/> for conciseness.<wbr/></p>
+<p>Linear mapping:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [ 0,<wbr/> 0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0 ]
+</code></pre>
+<p><img alt="Linear mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png"/></p>
+<p>Invert mapping:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [ 0,<wbr/> 1.<wbr/>0,<wbr/> 1.<wbr/>0,<wbr/> 0 ]
+</code></pre>
+<p><img alt="Inverting mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png"/></p>
+<p>Gamma 1/<wbr/>2.<wbr/>2 mapping,<wbr/> with 16 control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [
+  0.<wbr/>0000,<wbr/> 0.<wbr/>0000,<wbr/> 0.<wbr/>0667,<wbr/> 0.<wbr/>2920,<wbr/> 0.<wbr/>1333,<wbr/> 0.<wbr/>4002,<wbr/> 0.<wbr/>2000,<wbr/> 0.<wbr/>4812,<wbr/>
+  0.<wbr/>2667,<wbr/> 0.<wbr/>5484,<wbr/> 0.<wbr/>3333,<wbr/> 0.<wbr/>6069,<wbr/> 0.<wbr/>4000,<wbr/> 0.<wbr/>6594,<wbr/> 0.<wbr/>4667,<wbr/> 0.<wbr/>7072,<wbr/>
+  0.<wbr/>5333,<wbr/> 0.<wbr/>7515,<wbr/> 0.<wbr/>6000,<wbr/> 0.<wbr/>7928,<wbr/> 0.<wbr/>6667,<wbr/> 0.<wbr/>8317,<wbr/> 0.<wbr/>7333,<wbr/> 0.<wbr/>8685,<wbr/>
+  0.<wbr/>8000,<wbr/> 0.<wbr/>9035,<wbr/> 0.<wbr/>8667,<wbr/> 0.<wbr/>9370,<wbr/> 0.<wbr/>9333,<wbr/> 0.<wbr/>9691,<wbr/> 1.<wbr/>0000,<wbr/> 1.<wbr/>0000 ]
+</code></pre>
+<p><img alt="Gamma = 1/2.2 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png"/></p>
+<p>Standard sRGB gamma mapping,<wbr/> per IEC 61966-2-1:1999,<wbr/> with 16 control points:</p>
+<pre><code><a href="#controls_android.tonemap.curveRed">android.<wbr/>tonemap.<wbr/>curve<wbr/>Red</a> = [
+  0.<wbr/>0000,<wbr/> 0.<wbr/>0000,<wbr/> 0.<wbr/>0667,<wbr/> 0.<wbr/>2864,<wbr/> 0.<wbr/>1333,<wbr/> 0.<wbr/>4007,<wbr/> 0.<wbr/>2000,<wbr/> 0.<wbr/>4845,<wbr/>
+  0.<wbr/>2667,<wbr/> 0.<wbr/>5532,<wbr/> 0.<wbr/>3333,<wbr/> 0.<wbr/>6125,<wbr/> 0.<wbr/>4000,<wbr/> 0.<wbr/>6652,<wbr/> 0.<wbr/>4667,<wbr/> 0.<wbr/>7130,<wbr/>
+  0.<wbr/>5333,<wbr/> 0.<wbr/>7569,<wbr/> 0.<wbr/>6000,<wbr/> 0.<wbr/>7977,<wbr/> 0.<wbr/>6667,<wbr/> 0.<wbr/>8360,<wbr/> 0.<wbr/>7333,<wbr/> 0.<wbr/>8721,<wbr/>
+  0.<wbr/>8000,<wbr/> 0.<wbr/>9063,<wbr/> 0.<wbr/>8667,<wbr/> 0.<wbr/>9389,<wbr/> 0.<wbr/>9333,<wbr/> 0.<wbr/>9701,<wbr/> 1.<wbr/>0000,<wbr/> 1.<wbr/>0000 ]
+</code></pre>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For good quality of mapping,<wbr/> at least 128 control points are
+preferred.<wbr/></p>
+<p>A typical use case of this would be a gamma-1/<wbr/>2.<wbr/>2 curve,<wbr/> with as many
+control points used as are available.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.curve">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>tonemap.<wbr/>curve
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [java_public as tonemapCurve]</span>
+
+              <span class="entry_type_synthetic">[synthetic] </span>
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping /<wbr/> contrast /<wbr/> gamma curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a>
+is CONTRAST_<wbr/>CURVE.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemapCurve consist of three curves for each of red,<wbr/> green,<wbr/> and blue
+channels respectively.<wbr/> The following example uses the red channel as an
+example.<wbr/> The same logic applies to green and blue channel.<wbr/>
+Each channel's curve is defined by an array of control points:</p>
+<pre><code>curveRed =
+  [ P0(in,<wbr/> out),<wbr/> P1(in,<wbr/> out),<wbr/> P2(in,<wbr/> out),<wbr/> P3(in,<wbr/> out),<wbr/> ...,<wbr/> PN(in,<wbr/> out) ]
+2 &lt;= N &lt;= <a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a></code></pre>
+<p>These are sorted in order of increasing <code>Pin</code>; it is always
+guaranteed that input values 0.<wbr/>0 and 1.<wbr/>0 are included in the list to
+define a complete mapping.<wbr/> For input values between control points,<wbr/>
+the camera device must linearly interpolate between the control
+points.<wbr/></p>
+<p>Each curve can have an independent number of points,<wbr/> and the number
+of points can be less than max (that is,<wbr/> the request doesn't have to
+always provide a curve with number of points equivalent to
+<a href="#static_android.tonemap.maxCurvePoints">android.<wbr/>tonemap.<wbr/>max<wbr/>Curve<wbr/>Points</a>).<wbr/></p>
+<p>A few examples,<wbr/> and their corresponding graphical mappings; these
+only specify the red channel and the precision is limited to 4
+digits,<wbr/> for conciseness.<wbr/></p>
+<p>Linear mapping:</p>
+<pre><code>curveRed = [ (0,<wbr/> 0),<wbr/> (1.<wbr/>0,<wbr/> 1.<wbr/>0) ]
+</code></pre>
+<p><img alt="Linear mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/linear_tonemap.png"/></p>
+<p>Invert mapping:</p>
+<pre><code>curveRed = [ (0,<wbr/> 1.<wbr/>0),<wbr/> (1.<wbr/>0,<wbr/> 0) ]
+</code></pre>
+<p><img alt="Inverting mapping curve" src="images/camera2/metadata/android.tonemap.curveRed/inverse_tonemap.png"/></p>
+<p>Gamma 1/<wbr/>2.<wbr/>2 mapping,<wbr/> with 16 control points:</p>
+<pre><code>curveRed = [
+  (0.<wbr/>0000,<wbr/> 0.<wbr/>0000),<wbr/> (0.<wbr/>0667,<wbr/> 0.<wbr/>2920),<wbr/> (0.<wbr/>1333,<wbr/> 0.<wbr/>4002),<wbr/> (0.<wbr/>2000,<wbr/> 0.<wbr/>4812),<wbr/>
+  (0.<wbr/>2667,<wbr/> 0.<wbr/>5484),<wbr/> (0.<wbr/>3333,<wbr/> 0.<wbr/>6069),<wbr/> (0.<wbr/>4000,<wbr/> 0.<wbr/>6594),<wbr/> (0.<wbr/>4667,<wbr/> 0.<wbr/>7072),<wbr/>
+  (0.<wbr/>5333,<wbr/> 0.<wbr/>7515),<wbr/> (0.<wbr/>6000,<wbr/> 0.<wbr/>7928),<wbr/> (0.<wbr/>6667,<wbr/> 0.<wbr/>8317),<wbr/> (0.<wbr/>7333,<wbr/> 0.<wbr/>8685),<wbr/>
+  (0.<wbr/>8000,<wbr/> 0.<wbr/>9035),<wbr/> (0.<wbr/>8667,<wbr/> 0.<wbr/>9370),<wbr/> (0.<wbr/>9333,<wbr/> 0.<wbr/>9691),<wbr/> (1.<wbr/>0000,<wbr/> 1.<wbr/>0000) ]
+</code></pre>
+<p><img alt="Gamma = 1/2.2 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/gamma_tonemap.png"/></p>
+<p>Standard sRGB gamma mapping,<wbr/> per IEC 61966-2-1:1999,<wbr/> with 16 control points:</p>
+<pre><code>curveRed = [
+  (0.<wbr/>0000,<wbr/> 0.<wbr/>0000),<wbr/> (0.<wbr/>0667,<wbr/> 0.<wbr/>2864),<wbr/> (0.<wbr/>1333,<wbr/> 0.<wbr/>4007),<wbr/> (0.<wbr/>2000,<wbr/> 0.<wbr/>4845),<wbr/>
+  (0.<wbr/>2667,<wbr/> 0.<wbr/>5532),<wbr/> (0.<wbr/>3333,<wbr/> 0.<wbr/>6125),<wbr/> (0.<wbr/>4000,<wbr/> 0.<wbr/>6652),<wbr/> (0.<wbr/>4667,<wbr/> 0.<wbr/>7130),<wbr/>
+  (0.<wbr/>5333,<wbr/> 0.<wbr/>7569),<wbr/> (0.<wbr/>6000,<wbr/> 0.<wbr/>7977),<wbr/> (0.<wbr/>6667,<wbr/> 0.<wbr/>8360),<wbr/> (0.<wbr/>7333,<wbr/> 0.<wbr/>8721),<wbr/>
+  (0.<wbr/>8000,<wbr/> 0.<wbr/>9063),<wbr/> (0.<wbr/>8667,<wbr/> 0.<wbr/>9389),<wbr/> (0.<wbr/>9333,<wbr/> 0.<wbr/>9701),<wbr/> (1.<wbr/>0000,<wbr/> 1.<wbr/>0000) ]
+</code></pre>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This entry is created by the framework from the curveRed,<wbr/> curveGreen and
+curveBlue entries.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.mode">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>mode
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CONTRAST_CURVE</span>
+                    <span class="entry_type_enum_notes"><p>Use the tone mapping curve specified in
+the <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>* entries.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by
+<a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw
+sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FAST</span>
+                    <span class="entry_type_enum_notes"><p>Advanced gamma mapping and color enhancement may be applied,<wbr/> without
+reducing frame rate compared to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">HIGH_QUALITY</span>
+                    <span class="entry_type_enum_notes"><p>High-quality gamma mapping and color enhancement will be applied,<wbr/> at
+the cost of possibly reduced frame rate compared to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">GAMMA_VALUE</span>
+                    <span class="entry_type_enum_notes"><p>Use the gamma value specified in <a href="#controls_android.tonemap.gamma">android.<wbr/>tonemap.<wbr/>gamma</a> to peform
+tonemapping.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by <a href="#controls_android.tonemap.gamma">android.<wbr/>tonemap.<wbr/>gamma</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw sensor output.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">PRESET_CURVE</span>
+                    <span class="entry_type_enum_notes"><p>Use the preset tonemapping curve specified in
+<a href="#controls_android.tonemap.presetCurve">android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve</a> to peform tonemapping.<wbr/></p>
+<p>All color enhancement and tonemapping must be disabled,<wbr/> except
+for applying the tonemapping curve specified by
+<a href="#controls_android.tonemap.presetCurve">android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve</a>.<wbr/></p>
+<p>Must not slow down frame rate relative to raw sensor output.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>High-level global contrast/<wbr/>gamma/<wbr/>tonemapping control.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p><a href="#static_android.tonemap.availableToneMapModes">android.<wbr/>tonemap.<wbr/>available<wbr/>Tone<wbr/>Map<wbr/>Modes</a></p>
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When switching to an application-defined contrast curve by setting
+<a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> to CONTRAST_<wbr/>CURVE,<wbr/> the curve is defined
+per-channel with a set of <code>(in,<wbr/> out)</code> points that specify the
+mapping from input high-bit-depth pixel value to the output
+low-bit-depth value.<wbr/>  Since the actual pixel ranges of both input
+and output may change depending on the camera pipeline,<wbr/> the values
+are specified by normalized floating-point numbers.<wbr/></p>
+<p>More-complex color mapping operations such as 3D color look-up
+tables,<wbr/> selective chroma enhancement,<wbr/> or other non-linear color
+transforms will be disabled when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+CONTRAST_<wbr/>CURVE.<wbr/></p>
+<p>When using either FAST or HIGH_<wbr/>QUALITY,<wbr/> the camera device will
+emit its own tonemap curve in <a href="#controls_android.tonemap.curve">android.<wbr/>tonemap.<wbr/>curve</a>.<wbr/>
+These values are always available,<wbr/> and as close as possible to the
+actually used nonlinear/<wbr/>nonglobal transforms.<wbr/></p>
+<p>If a request is sent with CONTRAST_<wbr/>CURVE with the camera device's
+provided curve in FAST or HIGH_<wbr/>QUALITY,<wbr/> the image's tonemap will be
+roughly the same.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.gamma">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>gamma
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+GAMMA_<wbr/>VALUE</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemap curve will be defined the following formula:
+* OUT = pow(IN,<wbr/> 1.<wbr/>0 /<wbr/> gamma)
+where IN and OUT is the input pixel value scaled to range [0.<wbr/>0,<wbr/> 1.<wbr/>0],<wbr/>
+pow is the power function and gamma is the gamma value specified by this
+key.<wbr/></p>
+<p>The same curve will be applied to all color channels.<wbr/> The camera device
+may clip the input gamma value to its supported range.<wbr/> The actual applied
+value will be returned in capture result.<wbr/></p>
+<p>The valid range of gamma value varies on different devices,<wbr/> but values
+within [1.<wbr/>0,<wbr/> 5.<wbr/>0] are guaranteed not to be clipped.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="dynamic_android.tonemap.presetCurve">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>tonemap.<wbr/>preset<wbr/>Curve
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">SRGB</span>
+                    <span class="entry_type_enum_notes"><p>Tonemapping curve is defined by sRGB</p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">REC709</span>
+                    <span class="entry_type_enum_notes"><p>Tonemapping curve is defined by ITU-R BT.<wbr/>709</p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Tonemapping curve to use when <a href="#controls_android.tonemap.mode">android.<wbr/>tonemap.<wbr/>mode</a> is
+PRESET_<wbr/>CURVE</p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The tonemap curve will be defined by specified standard.<wbr/></p>
+<p>sRGB (approximated by 16 control points):</p>
+<p><img alt="sRGB tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/srgb_tonemap.png"/></p>
+<p>Rec.<wbr/> 709 (approximated by 16 control points):</p>
+<p><img alt="Rec. 709 tonemapping curve" src="images/camera2/metadata/android.tonemap.curveRed/rec709_tonemap.png"/></p>
+<p>Note that above figures show a 16 control points approximation of preset
+curves.<wbr/> Camera devices may apply a different approximation to the curve.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_led" class="section">led</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.led.transmit">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>led.<wbr/>transmit
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [hidden as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This LED is nominally used to indicate to the user
+that the camera is powered on and may be streaming images back to the
+Application Processor.<wbr/> In certain rare circumstances,<wbr/> the OS may
+disable this when video is processed locally and not transmitted to
+any untrusted applications.<wbr/></p>
+<p>In particular,<wbr/> the LED <em>must</em> always be on when the data could be
+transmitted off the device.<wbr/> The LED <em>should</em> always be on whenever
+data is stored locally on the device.<wbr/></p>
+<p>The LED <em>may</em> be off if a trusted application is using the data that
+doesn't violate the above rules.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.led.transmit">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>led.<wbr/>transmit
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [hidden as boolean]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This LED is nominally used to indicate to the user
+that the camera is powered on and may be streaming images back to the
+Application Processor.<wbr/> In certain rare circumstances,<wbr/> the OS may
+disable this when video is processed locally and not transmitted to
+any untrusted applications.<wbr/></p>
+<p>In particular,<wbr/> the LED <em>must</em> always be on when the data could be
+transmitted off the device.<wbr/> The LED <em>should</em> always be on whenever
+data is stored locally on the device.<wbr/></p>
+<p>The LED <em>may</em> be off if a trusted application is using the data that
+doesn't violate the above rules.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.led.availableLeds">
+            <td class="entry_name
+             " rowspan="1">
+              android.<wbr/>led.<wbr/>available<wbr/>Leds
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n
+                </span>
+              <span class="entry_type_visibility"> [hidden]</span>
+
+
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">TRANSMIT</span>
+                    <span class="entry_type_enum_notes"><p><a href="#controls_android.led.transmit">android.<wbr/>led.<wbr/>transmit</a> control is used.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>A list of camera LEDs that are available on this system.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_info" class="section">info</td></tr>
+
+
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.info.supportedHardwareLevel">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>info.<wbr/>supported<wbr/>Hardware<wbr/>Level
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">LIMITED</span>
+                    <span class="entry_type_enum_notes"><p>This camera device does not have enough capabilities to qualify as a <code>FULL</code> device or
+better.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>All <code>LIMITED</code> devices support the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability,<wbr/> indicating basic
+support for color image capture.<wbr/> The only exception is that the device may
+alternatively support only the <code>DEPTH_<wbr/>OUTPUT</code> capability,<wbr/> if it can only output depth
+measurements and not color images.<wbr/></p>
+<p><code>LIMITED</code> devices and above require the use of <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a>
+to lock exposure metering (and calculate flash power,<wbr/> for cameras with flash) before
+capturing a high-quality still image.<wbr/></p>
+<p>A <code>LIMITED</code> device that only lists the <code>BACKWARDS_<wbr/>COMPATIBLE</code> capability is only
+required to support full-automatic operation and post-processing (<code>OFF</code> is not
+supported for <a href="#controls_android.control.aeMode">android.<wbr/>control.<wbr/>ae<wbr/>Mode</a>,<wbr/> <a href="#controls_android.control.afMode">android.<wbr/>control.<wbr/>af<wbr/>Mode</a>,<wbr/> or
+<a href="#controls_android.control.awbMode">android.<wbr/>control.<wbr/>awb<wbr/>Mode</a>)</p>
+<p>Additional capabilities may optionally be supported by a <code>LIMITED</code>-level device,<wbr/> and
+can be checked for in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">FULL</span>
+                    <span class="entry_type_enum_notes"><p>This camera device is capable of supporting advanced imaging applications.<wbr/></p>
+<p>The stream configurations listed in the <code>FULL</code>,<wbr/> <code>LEGACY</code> and <code>LIMITED</code> tables in the
+<a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a> documentation are guaranteed to be supported.<wbr/></p>
+<p>A <code>FULL</code> device will support below capabilities:</p>
+<ul>
+<li><code>BURST_<wbr/>CAPTURE</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>BURST_<wbr/>CAPTURE</code>)</li>
+<li>Per frame control (<a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> <code>==</code> PER_<wbr/>FRAME_<wbr/>CONTROL)</li>
+<li>Manual sensor control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains <code>MANUAL_<wbr/>SENSOR</code>)</li>
+<li>Manual post-processing control (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>MANUAL_<wbr/>POST_<wbr/>PROCESSING</code>)</li>
+<li>The required exposure time range defined in <a href="#static_android.sensor.info.exposureTimeRange">android.<wbr/>sensor.<wbr/>info.<wbr/>exposure<wbr/>Time<wbr/>Range</a></li>
+<li>The required maxFrameDuration defined in <a href="#static_android.sensor.info.maxFrameDuration">android.<wbr/>sensor.<wbr/>info.<wbr/>max<wbr/>Frame<wbr/>Duration</a></li>
+</ul>
+<p>Note:
+Pre-API level 23,<wbr/> FULL devices also supported arbitrary cropping region
+(<a href="#static_android.scaler.croppingType">android.<wbr/>scaler.<wbr/>cropping<wbr/>Type</a> <code>== FREEFORM</code>); this requirement was relaxed in API level
+23,<wbr/> and <code>FULL</code> devices may only support <code>CENTERED</code> cropping.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">LEGACY</span>
+                    <span class="entry_type_enum_notes"><p>This camera device is running in backward compatibility mode.<wbr/></p>
+<p>Only the stream configurations listed in the <code>LEGACY</code> table in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are supported.<wbr/></p>
+<p>A <code>LEGACY</code> device does not support per-frame control,<wbr/> manual sensor control,<wbr/> manual
+post-processing,<wbr/> arbitrary cropping regions,<wbr/> and has relaxed performance constraints.<wbr/>
+No additional capabilities beyond <code>BACKWARD_<wbr/>COMPATIBLE</code> will ever be listed by a
+<code>LEGACY</code> device in <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a>.<wbr/></p>
+<p>In addition,<wbr/> the <a href="#controls_android.control.aePrecaptureTrigger">android.<wbr/>control.<wbr/>ae<wbr/>Precapture<wbr/>Trigger</a> is not functional on <code>LEGACY</code>
+devices.<wbr/> Instead,<wbr/> every request that includes a JPEG-format output target is treated
+as triggering a still capture,<wbr/> internally executing a precapture trigger.<wbr/>  This may
+fire the flash for flash power metering during precapture,<wbr/> and then fire the flash
+for the final capture,<wbr/> if a flash is available on the device and the AE mode is set to
+enable the flash.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">3</span>
+                    <span class="entry_type_enum_notes"><p>This camera device is capable of YUV reprocessing and RAW data capture,<wbr/> in addition to
+FULL-level capabilities.<wbr/></p>
+<p>The stream configurations listed in the <code>LEVEL_<wbr/>3</code>,<wbr/> <code>RAW</code>,<wbr/> <code>FULL</code>,<wbr/> <code>LEGACY</code> and
+<code>LIMITED</code> tables in the <a href="https://developer.android.com/reference/android/hardware/camera2/CameraDevice.html#createCaptureSession">createCaptureSession</a>
+documentation are guaranteed to be supported.<wbr/></p>
+<p>The following additional capabilities are guaranteed to be supported:</p>
+<ul>
+<li><code>YUV_<wbr/>REPROCESSING</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>YUV_<wbr/>REPROCESSING</code>)</li>
+<li><code>RAW</code> capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains
+  <code>RAW</code>)</li>
+</ul></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Generally classifies the overall set of the camera device functionality.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The supported hardware level is a high-level description of the camera device's
+capabilities,<wbr/> summarizing several capabilities into one field.<wbr/>  Each level adds additional
+features to the previous one,<wbr/> and is always a strict superset of the previous level.<wbr/>
+The ordering is <code>LEGACY &lt; LIMITED &lt; FULL &lt; LEVEL_<wbr/>3</code>.<wbr/></p>
+<p>Starting from <code>LEVEL_<wbr/>3</code>,<wbr/> the level enumerations are guaranteed to be in increasing
+numerical value as well.<wbr/> To check if a given device is at least at a given hardware level,<wbr/>
+the following code snippet can be used:</p>
+<pre><code>//<wbr/> Returns true if the device supports the required hardware level,<wbr/> or better.<wbr/>
+boolean isHardwareLevelSupported(CameraCharacteristics c,<wbr/> int requiredLevel) {
+    int deviceLevel = c.<wbr/>get(Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL);
+    if (deviceLevel == Camera<wbr/>Characteristics.<wbr/>INFO_<wbr/>SUPPORTED_<wbr/>HARDWARE_<wbr/>LEVEL_<wbr/>LEGACY) {
+        return requiredLevel == deviceLevel;
+    }
+    //<wbr/> deviceLevel is not LEGACY,<wbr/> can use numerical sort
+    return requiredLevel &lt;= deviceLevel;
+}
+</code></pre>
+<p>At a high level,<wbr/> the levels are:</p>
+<ul>
+<li><code>LEGACY</code> devices operate in a backwards-compatibility mode for older
+  Android devices,<wbr/> and have very limited capabilities.<wbr/></li>
+<li><code>LIMITED</code> devices represent the
+  baseline feature set,<wbr/> and may also include additional capabilities that are
+  subsets of <code>FULL</code>.<wbr/></li>
+<li><code>FULL</code> devices additionally support per-frame manual control of sensor,<wbr/> flash,<wbr/> lens and
+  post-processing settings,<wbr/> and image capture at a high rate.<wbr/></li>
+<li><code>LEVEL_<wbr/>3</code> devices additionally support YUV reprocessing and RAW image capture,<wbr/> along
+  with additional output stream configurations.<wbr/></li>
+</ul>
+<p>See the individual level enums for full descriptions of the supported capabilities.<wbr/>  The
+<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> entry describes the device's capabilities at a
+finer-grain level,<wbr/> if needed.<wbr/> In addition,<wbr/> many controls have their available settings or
+ranges defined in individual <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html">CameraCharacteristics</a> entries.<wbr/></p>
+<p>Some features are not part of any particular hardware level or capability and must be
+queried separately.<wbr/> These include:</p>
+<ul>
+<li>Calibrated timestamps (<a href="#static_android.sensor.info.timestampSource">android.<wbr/>sensor.<wbr/>info.<wbr/>timestamp<wbr/>Source</a> <code>==</code> REALTIME)</li>
+<li>Precision lens control (<a href="#static_android.lens.info.focusDistanceCalibration">android.<wbr/>lens.<wbr/>info.<wbr/>focus<wbr/>Distance<wbr/>Calibration</a> <code>==</code> CALIBRATED)</li>
+<li>Face detection (<a href="#static_android.statistics.info.availableFaceDetectModes">android.<wbr/>statistics.<wbr/>info.<wbr/>available<wbr/>Face<wbr/>Detect<wbr/>Modes</a>)</li>
+<li>Optical or electrical image stabilization
+  (<a href="#static_android.lens.info.availableOpticalStabilization">android.<wbr/>lens.<wbr/>info.<wbr/>available<wbr/>Optical<wbr/>Stabilization</a>,<wbr/>
+   <a href="#static_android.control.availableVideoStabilizationModes">android.<wbr/>control.<wbr/>available<wbr/>Video<wbr/>Stabilization<wbr/>Modes</a>)</li>
+</ul>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The camera 3 HAL device can implement one of three possible operational modes; LIMITED,<wbr/>
+FULL,<wbr/> and LEVEL_<wbr/>3.<wbr/></p>
+<p>FULL support or better is expected from new higher-end devices.<wbr/> Limited
+mode has hardware requirements roughly in line with those for a camera HAL device v1
+implementation,<wbr/> and is expected from older or inexpensive devices.<wbr/> Each level is a strict
+superset of the previous level,<wbr/> and they share the same essential operational flow.<wbr/></p>
+<p>For full details refer to "S3.<wbr/> Operational Modes" in camera3.<wbr/>h</p>
+<p>Camera HAL3+ must not implement LEGACY mode.<wbr/> It is there for backwards compatibility in
+the <code>android.<wbr/>hardware.<wbr/>camera2</code> user-facing API only on HALv1 devices,<wbr/> and is implemented
+by the camera framework code.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_blackLevel" class="section">blackLevel</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.blackLevel.lock">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>black<wbr/>Level.<wbr/>lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether black-level compensation is locked
+to its current values,<wbr/> or is free to vary.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When set to <code>true</code> (ON),<wbr/> the values used for black-level
+compensation will not change until the lock is set to
+<code>false</code> (OFF).<wbr/></p>
+<p>Since changes to certain capture parameters (such as
+exposure time) may require resetting of black level
+compensation,<wbr/> the camera device must report whether setting
+the black level lock was successful in the output result
+metadata.<wbr/></p>
+<p>For example,<wbr/> if a sequence of requests is as follows:</p>
+<ul>
+<li>Request 1: Exposure = 10ms,<wbr/> Black level lock = OFF</li>
+<li>Request 2: Exposure = 10ms,<wbr/> Black level lock = ON</li>
+<li>Request 3: Exposure = 10ms,<wbr/> Black level lock = ON</li>
+<li>Request 4: Exposure = 20ms,<wbr/> Black level lock = ON</li>
+<li>Request 5: Exposure = 20ms,<wbr/> Black level lock = ON</li>
+<li>Request 6: Exposure = 20ms,<wbr/> Black level lock = ON</li>
+</ul>
+<p>And the exposure change in Request 4 requires the camera
+device to reset the black level offsets,<wbr/> then the output
+result metadata is expected to be:</p>
+<ul>
+<li>Result 1: Exposure = 10ms,<wbr/> Black level lock = OFF</li>
+<li>Result 2: Exposure = 10ms,<wbr/> Black level lock = ON</li>
+<li>Result 3: Exposure = 10ms,<wbr/> Black level lock = ON</li>
+<li>Result 4: Exposure = 20ms,<wbr/> Black level lock = OFF</li>
+<li>Result 5: Exposure = 20ms,<wbr/> Black level lock = ON</li>
+<li>Result 6: Exposure = 20ms,<wbr/> Black level lock = ON</li>
+</ul>
+<p>This indicates to the application that on frame 4,<wbr/> black
+levels were reset due to exposure value changes,<wbr/> and pixel
+values may not be consistent across captures.<wbr/></p>
+<p>The camera device will maintain the lock to the extent
+possible,<wbr/> only overriding the lock to OFF when changes to
+other request parameters require a black level recalculation
+or reset.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If for some reason black level locking is no longer possible
+(for example,<wbr/> the analog gain has changed,<wbr/> which forces
+black level offsets to be recalculated),<wbr/> then the HAL must
+override this request (and it must report 'OFF' when this
+does happen) until the next capture for which locking is
+possible again.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.blackLevel.lock">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>black<wbr/>Level.<wbr/>lock
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[full] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OFF</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">ON</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Whether black-level compensation is locked
+to its current values,<wbr/> or is free to vary.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_HAL2">HAL2</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Whether the black level offset was locked for this frame.<wbr/>  Should be
+ON if <a href="#controls_android.blackLevel.lock">android.<wbr/>black<wbr/>Level.<wbr/>lock</a> was ON in the capture request,<wbr/> unless
+a change in other capture settings forced the camera device to
+perform a black level reset.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If for some reason black level locking is no longer possible
+(for example,<wbr/> the analog gain has changed,<wbr/> which forces
+black level offsets to be recalculated),<wbr/> then the HAL must
+override this request (and it must report 'OFF' when this
+does happen) until the next capture for which locking is
+possible again.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_sync" class="section">sync</td></tr>
+
+
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.sync.frameNumber">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sync.<wbr/>frame<wbr/>Number
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int64</span>
+
+              <span class="entry_type_visibility"> [ndk_public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">CONVERGING</span>
+                    <span class="entry_type_enum_value">-1</span>
+                    <span class="entry_type_enum_notes"><p>The current result is not yet fully synchronized to any request.<wbr/></p>
+<p>Synchronization is in progress,<wbr/> and reading metadata from this
+result may include a mix of data that have taken effect since the
+last synchronization time.<wbr/></p>
+<p>In some future result,<wbr/> within <a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a> frames,<wbr/>
+this value will update to the actual frame number frame number
+the result is guaranteed to be synchronized to (as long as the
+request settings remain constant).<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">UNKNOWN</span>
+                    <span class="entry_type_enum_value">-2</span>
+                    <span class="entry_type_enum_notes"><p>The current result's synchronization status is unknown.<wbr/></p>
+<p>The result may have already converged,<wbr/> or it may be in
+progress.<wbr/>  Reading from this result may include some mix
+of settings from past requests.<wbr/></p>
+<p>After a settings change,<wbr/> the new settings will eventually all
+take effect for the output buffers and results.<wbr/> However,<wbr/> this
+value will not change when that happens.<wbr/> Altering settings
+rapidly may provide outcomes using mixes of settings from recent
+requests.<wbr/></p>
+<p>This value is intended primarily for backwards compatibility with
+the older camera implementations (for android.<wbr/>hardware.<wbr/>Camera).<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The frame number corresponding to the last request
+with which the output result (metadata + buffers) has been fully
+synchronized.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+              <p>Either a non-negative value corresponding to a
+<code>frame_<wbr/>number</code>,<wbr/> or one of the two enums (CONVERGING /<wbr/> UNKNOWN).<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>When a request is submitted to the camera device,<wbr/> there is usually a
+delay of several frames before the controls get applied.<wbr/> A camera
+device may either choose to account for this delay by implementing a
+pipeline and carefully submit well-timed atomic control updates,<wbr/> or
+it may start streaming control changes that span over several frame
+boundaries.<wbr/></p>
+<p>In the latter case,<wbr/> whenever a request's settings change relative to
+the previous submitted request,<wbr/> the full set of changes may take
+multiple frame durations to fully take effect.<wbr/> Some settings may
+take effect sooner (in less frame durations) than others.<wbr/></p>
+<p>While a set of control changes are being propagated,<wbr/> this value
+will be CONVERGING.<wbr/></p>
+<p>Once it is fully known that a set of control changes have been
+finished propagating,<wbr/> and the resulting updated control settings
+have been read back by the camera device,<wbr/> this value will be set
+to a non-negative frame number (corresponding to the request to
+which the results have synchronized to).<wbr/></p>
+<p>Older camera device implementations may not have a way to detect
+when all camera controls have been applied,<wbr/> and will always set this
+value to UNKNOWN.<wbr/></p>
+<p>FULL capability devices will always have this value set to the
+frame number of the request corresponding to this result.<wbr/></p>
+<p><em>Further details</em>:</p>
+<ul>
+<li>Whenever a request differs from the last request,<wbr/> any future
+results not yet returned may have this value set to CONVERGING (this
+could include any in-progress captures not yet returned by the camera
+device,<wbr/> for more details see pipeline considerations below).<wbr/></li>
+<li>Submitting a series of multiple requests that differ from the
+previous request (e.<wbr/>g.<wbr/> r1,<wbr/> r2,<wbr/> r3 s.<wbr/>t.<wbr/> r1 != r2 != r3)
+moves the new synchronization frame to the last non-repeating
+request (using the smallest frame number from the contiguous list of
+repeating requests).<wbr/></li>
+<li>Submitting the same request repeatedly will not change this value
+to CONVERGING,<wbr/> if it was already a non-negative value.<wbr/></li>
+<li>When this value changes to non-negative,<wbr/> that means that all of the
+metadata controls from the request have been applied,<wbr/> all of the
+metadata controls from the camera device have been read to the
+updated values (into the result),<wbr/> and all of the graphics buffers
+corresponding to this result are also synchronized to the request.<wbr/></li>
+</ul>
+<p><em>Pipeline considerations</em>:</p>
+<p>Submitting a request with updated controls relative to the previously
+submitted requests may also invalidate the synchronization state
+of all the results corresponding to currently in-flight requests.<wbr/></p>
+<p>In other words,<wbr/> results for this current request and up to
+<a href="#static_android.request.pipelineMaxDepth">android.<wbr/>request.<wbr/>pipeline<wbr/>Max<wbr/>Depth</a> prior requests may have their
+<a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> change to CONVERGING.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>Using UNKNOWN here is illegal unless <a href="#static_android.sync.maxLatency">android.<wbr/>sync.<wbr/>max<wbr/>Latency</a>
+is also UNKNOWN.<wbr/></p>
+<p>FULL capability devices should simply set this value to the
+<code>frame_<wbr/>number</code> of the request this result corresponds to.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.sync.maxLatency">
+            <td class="entry_name
+             " rowspan="5">
+              android.<wbr/>sync.<wbr/>max<wbr/>Latency
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+
+              <span class="entry_type_visibility"> [public]</span>
+
+
+              <span class="entry_type_hwlevel">[legacy] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">PER_FRAME_CONTROL</span>
+                    <span class="entry_type_enum_value">0</span>
+                    <span class="entry_type_enum_notes"><p>Every frame has the requests immediately applied.<wbr/></p>
+<p>Changing controls over multiple requests one after another will
+produce results that have those controls applied atomically
+each frame.<wbr/></p>
+<p>All FULL capability devices will have this as their maxLatency.<wbr/></p></span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">UNKNOWN</span>
+                    <span class="entry_type_enum_value">-1</span>
+                    <span class="entry_type_enum_notes"><p>Each new frame has some subset (potentially the entire set)
+of the past requests applied to the camera settings.<wbr/></p>
+<p>By submitting a series of identical requests,<wbr/> the camera device
+will eventually have the camera settings applied,<wbr/> but it is
+unknown when that exact point will be.<wbr/></p>
+<p>All LEGACY capability devices will have this as their maxLatency.<wbr/></p></span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximum number of frames that can occur after a request
+(different than the previous) has been submitted,<wbr/> and before the
+result's state becomes synchronized.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Frame counts
+            </td>
+
+            <td class="entry_range">
+              <p>A positive value,<wbr/> PER_<wbr/>FRAME_<wbr/>CONTROL,<wbr/> or UNKNOWN.<wbr/></p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_V1">V1</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This defines the maximum distance (in number of metadata results),<wbr/>
+between the frame number of the request that has new controls to apply
+and the frame number of the result that has all the controls applied.<wbr/></p>
+<p>In other words this acts as an upper boundary for how many frames
+must occur before the camera device knows for a fact that the new
+submitted camera settings have been applied in outgoing frames.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">HAL Implementation Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>For example if maxLatency was 2,<wbr/></p>
+<pre><code>initial request = X (repeating)
+request1 = X
+request2 = Y
+request3 = Y
+request4 = Y
+
+where requestN has frameNumber N,<wbr/> and the first of the repeating
+initial request's has frameNumber F (and F &lt; 1).<wbr/>
+
+initial result = X' + { <a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == F }
+result1 = X' + { <a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == F }
+result2 = X' + { <a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == CONVERGING }
+result3 = X' + { <a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == CONVERGING }
+result4 = X' + { <a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == 2 }
+
+where resultN has frameNumber N.<wbr/>
+</code></pre>
+<p>Since <code>result4</code> has a <code>frameNumber == 4</code> and
+<code><a href="#dynamic_android.sync.frameNumber">android.<wbr/>sync.<wbr/>frame<wbr/>Number</a> == 2</code>,<wbr/> the distance is clearly
+<code>4 - 2 = 2</code>.<wbr/></p>
+<p>Use <code>frame_<wbr/>count</code> from camera3_<wbr/>request_<wbr/>t instead of
+<a href="#controls_android.request.frameCount">android.<wbr/>request.<wbr/>frame<wbr/>Count</a> or
+<code><a href="https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html#getFrameNumber">CaptureResult#getFrameNumber</a></code>.<wbr/></p>
+<p>LIMITED devices are strongly encouraged to use a non-negative
+value.<wbr/> If UNKNOWN is used here then app developers do not have a way
+to know when sensor settings have been applied.<wbr/></p>
+            </td>
+          </tr>
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_reprocess" class="section">reprocess</td></tr>
+
+
+      <tr><td colspan="6" class="kind">controls</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="controls_android.reprocess.effectiveExposureFactor">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of exposure time increase factor applied to the original output
+frame by the application processing before sending for reprocessing.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Relative exposure time increase factor.<wbr/>
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 1.<wbr/>0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is optional,<wbr/> and will be supported if the camera device supports YUV_<wbr/>REPROCESSING
+capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains YUV_<wbr/>REPROCESSING).<wbr/></p>
+<p>For some YUV reprocessing use cases,<wbr/> the application may choose to filter the original
+output frames to effectively reduce the noise to the same level as a frame that was
+captured with longer exposure time.<wbr/> To be more specific,<wbr/> assuming the original captured
+images were captured with a sensitivity of S and an exposure time of T,<wbr/> the model in
+the camera device is that the amount of noise in the image would be approximately what
+would be expected if the original capture parameters had been a sensitivity of
+S/<wbr/>effectiveExposureFactor and an exposure time of T*effectiveExposureFactor,<wbr/> rather
+than S and T respectively.<wbr/> If the captured images were processed by the application
+before being sent for reprocessing,<wbr/> then the application may have used image processing
+algorithms and/<wbr/>or multi-frame image fusion to reduce the noise in the
+application-processed images (input images).<wbr/> By using the effectiveExposureFactor
+control,<wbr/> the application can communicate to the camera device the actual noise level
+improvement in the application-processed image.<wbr/> With this information,<wbr/> the camera
+device can select appropriate noise reduction and edge enhancement parameters to avoid
+excessive noise reduction (<a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a>) and insufficient edge
+enhancement (<a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a>) being applied to the reprocessed frames.<wbr/></p>
+<p>For example,<wbr/> for multi-frame image fusion use case,<wbr/> the application may fuse
+multiple output frames together to a final frame for reprocessing.<wbr/> When N image are
+fused into 1 image for reprocessing,<wbr/> the exposure time increase factor could be up to
+square root of N (based on a simple photon shot noise model).<wbr/> The camera device will
+adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+produce the best quality images.<wbr/></p>
+<p>This is relative factor,<wbr/> 1.<wbr/>0 indicates the application hasn't processed the input
+buffer in a way that affects its effective exposure time.<wbr/></p>
+<p>This control is only effective for YUV reprocessing capture request.<wbr/> For noise
+reduction reprocessing,<wbr/> it is only effective when <code><a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a> != OFF</code>.<wbr/>
+Similarly,<wbr/> for edge enhancement reprocessing,<wbr/> it is only effective when
+<code><a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a> != OFF</code>.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">dynamic</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="dynamic_android.reprocess.effectiveExposureFactor">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>reprocess.<wbr/>effective<wbr/>Exposure<wbr/>Factor
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">float</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The amount of exposure time increase factor applied to the original output
+frame by the application processing before sending for reprocessing.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Relative exposure time increase factor.<wbr/>
+            </td>
+
+            <td class="entry_range">
+              <p>&gt;= 1.<wbr/>0</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This is optional,<wbr/> and will be supported if the camera device supports YUV_<wbr/>REPROCESSING
+capability (<a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains YUV_<wbr/>REPROCESSING).<wbr/></p>
+<p>For some YUV reprocessing use cases,<wbr/> the application may choose to filter the original
+output frames to effectively reduce the noise to the same level as a frame that was
+captured with longer exposure time.<wbr/> To be more specific,<wbr/> assuming the original captured
+images were captured with a sensitivity of S and an exposure time of T,<wbr/> the model in
+the camera device is that the amount of noise in the image would be approximately what
+would be expected if the original capture parameters had been a sensitivity of
+S/<wbr/>effectiveExposureFactor and an exposure time of T*effectiveExposureFactor,<wbr/> rather
+than S and T respectively.<wbr/> If the captured images were processed by the application
+before being sent for reprocessing,<wbr/> then the application may have used image processing
+algorithms and/<wbr/>or multi-frame image fusion to reduce the noise in the
+application-processed images (input images).<wbr/> By using the effectiveExposureFactor
+control,<wbr/> the application can communicate to the camera device the actual noise level
+improvement in the application-processed image.<wbr/> With this information,<wbr/> the camera
+device can select appropriate noise reduction and edge enhancement parameters to avoid
+excessive noise reduction (<a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a>) and insufficient edge
+enhancement (<a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a>) being applied to the reprocessed frames.<wbr/></p>
+<p>For example,<wbr/> for multi-frame image fusion use case,<wbr/> the application may fuse
+multiple output frames together to a final frame for reprocessing.<wbr/> When N image are
+fused into 1 image for reprocessing,<wbr/> the exposure time increase factor could be up to
+square root of N (based on a simple photon shot noise model).<wbr/> The camera device will
+adjust the reprocessing noise reduction and edge enhancement parameters accordingly to
+produce the best quality images.<wbr/></p>
+<p>This is relative factor,<wbr/> 1.<wbr/>0 indicates the application hasn't processed the input
+buffer in a way that affects its effective exposure time.<wbr/></p>
+<p>This control is only effective for YUV reprocessing capture request.<wbr/> For noise
+reduction reprocessing,<wbr/> it is only effective when <code><a href="#controls_android.noiseReduction.mode">android.<wbr/>noise<wbr/>Reduction.<wbr/>mode</a> != OFF</code>.<wbr/>
+Similarly,<wbr/> for edge enhancement reprocessing,<wbr/> it is only effective when
+<code><a href="#controls_android.edge.mode">android.<wbr/>edge.<wbr/>mode</a> != OFF</code>.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.reprocess.maxCaptureStall">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>reprocess.<wbr/>max<wbr/>Capture<wbr/>Stall
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [java_public]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The maximal camera capture pipeline stall (in unit of frame count) introduced by a
+reprocess capture request.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              Number of frames.<wbr/>
+            </td>
+
+            <td class="entry_range">
+              <p>&lt;= 4</p>
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_REPROC">REPROC</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>The key describes the maximal interference that one reprocess (input) request
+can introduce to the camera simultaneous streaming of regular (output) capture
+requests,<wbr/> including repeating requests.<wbr/></p>
+<p>When a reprocessing capture request is submitted while a camera output repeating request
+(e.<wbr/>g.<wbr/> preview) is being served by the camera device,<wbr/> it may preempt the camera capture
+pipeline for at least one frame duration so that the camera device is unable to process
+the following capture request in time for the next sensor start of exposure boundary.<wbr/>
+When this happens,<wbr/> the application may observe a capture time gap (longer than one frame
+duration) between adjacent capture output frames,<wbr/> which usually exhibits as preview
+glitch if the repeating request output targets include a preview surface.<wbr/> This key gives
+the worst-case number of frame stall introduced by one reprocess request with any kind of
+formats/<wbr/>sizes combination.<wbr/></p>
+<p>If this key reports 0,<wbr/> it means a reprocess request doesn't introduce any glitch to the
+ongoing camera repeating request outputs,<wbr/> as if this reprocess request is never issued.<wbr/></p>
+<p>This key is supported if the camera device supports PRIVATE or YUV reprocessing (
+i.<wbr/>e.<wbr/> <a href="#static_android.request.availableCapabilities">android.<wbr/>request.<wbr/>available<wbr/>Capabilities</a> contains PRIVATE_<wbr/>REPROCESSING or
+YUV_<wbr/>REPROCESSING).<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+  <tr><td colspan="6" id="section_depth" class="section">depth</td></tr>
+
+
+      <tr><td colspan="6" class="kind">static</td></tr>
+
+      <thead class="entries_header">
+        <tr>
+          <th class="th_name">Property Name</th>
+          <th class="th_type">Type</th>
+          <th class="th_description">Description</th>
+          <th class="th_units">Units</th>
+          <th class="th_range">Range</th>
+          <th class="th_tags">Tags</th>
+        </tr>
+      </thead>
+
+      <tbody>
+
+        
+
+        
+
+        
+
+        
+
+                
+          <tr class="entry" id="static_android.depth.maxDepthSamples">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>depth.<wbr/>max<wbr/>Depth<wbr/>Samples
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int32</span>
+
+              <span class="entry_type_visibility"> [system]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Maximum number of points that a depth point cloud may contain.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If a camera device supports outputting depth range data in the form of a depth point
+cloud (<a href="https://developer.android.com/reference/android/graphics/ImageFormat.html#DEPTH_POINT_CLOUD">Image<wbr/>Format#DEPTH_<wbr/>POINT_<wbr/>CLOUD</a>),<wbr/> this is the maximum
+number of points an output buffer may contain.<wbr/></p>
+<p>Any given buffer may contain between 0 and maxDepthSamples points,<wbr/> inclusive.<wbr/>
+If output in the depth point cloud format is not supported,<wbr/> this entry will
+not be defined.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.depth.availableDepthStreamConfigurations">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Stream<wbr/>Configurations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">int32</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  n x 4
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfiguration]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">OUTPUT</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">INPUT</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>The available depth dataspace stream
+configurations that this camera device supports
+(i.<wbr/>e.<wbr/> format,<wbr/> width,<wbr/> height,<wbr/> output/<wbr/>input stream).<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>These are output stream configurations for use with
+dataSpace HAL_<wbr/>DATASPACE_<wbr/>DEPTH.<wbr/> The configurations are
+listed as <code>(format,<wbr/> width,<wbr/> height,<wbr/> input?)</code> tuples.<wbr/></p>
+<p>Only devices that support depth output for at least
+the HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>Y16 dense depth map may include
+this entry.<wbr/></p>
+<p>A device that also supports the HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>BLOB
+sparse depth point cloud must report a single entry for
+the format in this list as <code>(HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>BLOB,<wbr/>
+<a href="#static_android.depth.maxDepthSamples">android.<wbr/>depth.<wbr/>max<wbr/>Depth<wbr/>Samples</a>,<wbr/> 1,<wbr/> OUTPUT)</code> in addition to
+the entries for HAL_<wbr/>PIXEL_<wbr/>FORMAT_<wbr/>Y16.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.depth.availableDepthMinFrameDurations">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Min<wbr/>Frame<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This lists the minimum frame duration for each
+format/<wbr/>size combination for depth output formats.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              (format,<wbr/> width,<wbr/> height,<wbr/> ns) x n
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>This should correspond to the frame duration when only that
+stream is active,<wbr/> with all processing (typically in android.<wbr/>*.<wbr/>mode)
+set to either OFF or FAST.<wbr/></p>
+<p>When multiple streams are used in a request,<wbr/> the minimum frame
+duration will be max(individual stream min durations).<wbr/></p>
+<p>The minimum frame duration of a stream (of a particular format,<wbr/> size)
+is the same regardless of whether the stream is input or output.<wbr/></p>
+<p>See <a href="#controls_android.sensor.frameDuration">android.<wbr/>sensor.<wbr/>frame<wbr/>Duration</a> and
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a> for more details about
+calculating the max frame rate.<wbr/></p>
+<p>(Keep in sync with <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html#getOutputMinFrameDuration">StreamConfigurationMap#getOutputMinFrameDuration</a>)</p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.depth.availableDepthStallDurations">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>depth.<wbr/>available<wbr/>Depth<wbr/>Stall<wbr/>Durations
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name">int64</span>
+                <span class="entry_type_container">x</span>
+
+                <span class="entry_type_array">
+                  4 x n
+                </span>
+              <span class="entry_type_visibility"> [ndk_public as streamConfigurationDuration]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>This lists the maximum stall duration for each
+output format/<wbr/>size combination for depth streams.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+              (format,<wbr/> width,<wbr/> height,<wbr/> ns) x n
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+              <ul class="entry_tags">
+                  <li><a href="#tag_DEPTH">DEPTH</a></li>
+              </ul>
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>A stall duration is how much extra time would get added
+to the normal minimum frame duration for a repeating request
+that has streams with non-zero stall.<wbr/></p>
+<p>This functions similarly to
+<a href="#static_android.scaler.availableStallDurations">android.<wbr/>scaler.<wbr/>available<wbr/>Stall<wbr/>Durations</a> for depth
+streams.<wbr/></p>
+<p>All depth output stream formats may have a nonzero stall
+duration.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+                
+          <tr class="entry" id="static_android.depth.depthIsExclusive">
+            <td class="entry_name
+             " rowspan="3">
+              android.<wbr/>depth.<wbr/>depth<wbr/>Is<wbr/>Exclusive
+            </td>
+            <td class="entry_type">
+                <span class="entry_type_name entry_type_name_enum">byte</span>
+
+              <span class="entry_type_visibility"> [public as boolean]</span>
+
+
+              <span class="entry_type_hwlevel">[limited] </span>
+
+
+
+                <ul class="entry_type_enum">
+                  <li>
+                    <span class="entry_type_enum_name">FALSE</span>
+                  </li>
+                  <li>
+                    <span class="entry_type_enum_name">TRUE</span>
+                  </li>
+                </ul>
+
+            </td> <!-- entry_type -->
+
+            <td class="entry_description">
+              <p>Indicates whether a capture request may target both a
+DEPTH16 /<wbr/> DEPTH_<wbr/>POINT_<wbr/>CLOUD output,<wbr/> and normal color outputs (such as
+YUV_<wbr/>420_<wbr/>888,<wbr/> JPEG,<wbr/> or RAW) simultaneously.<wbr/></p>
+            </td>
+
+            <td class="entry_units">
+            </td>
+
+            <td class="entry_range">
+            </td>
+
+            <td class="entry_tags">
+            </td>
+
+          </tr>
+          <tr class="entries_header">
+            <th class="th_details" colspan="5">Details</th>
+          </tr>
+          <tr class="entry_cont">
+            <td class="entry_details" colspan="5">
+              <p>If TRUE,<wbr/> including both depth and color outputs in a single
+capture request is not supported.<wbr/> An application must interleave color
+and depth requests.<wbr/>  If FALSE,<wbr/> a single request can target both types
+of output.<wbr/></p>
+<p>Typically,<wbr/> this restriction exists on camera devices that
+need to emit a specific pattern or wavelength of light to
+measure depth values,<wbr/> which causes the color image to be
+corrupted during depth measurement.<wbr/></p>
+            </td>
+          </tr>
+
+
+          <tr class="entry_spacer"><td class="entry_spacer" colspan="6"></td></tr>
+           <!-- end of entry -->
+        
+        
+
+      <!-- end of kind -->
+      </tbody>
+
+  <!-- end of section -->
+<!-- </namespace> -->
+  </table>
+
+  <div class="tags" id="tag_index">
+    <h2>Tags</h2>
+    <ul>
+      <li id="tag_BC">BC - 
+        Needed for backwards compatibility with old Java API
+    
+        <ul class="tags_entries">
+          <li><a href="#controls_android.control.aeAntibandingMode">android.control.aeAntibandingMode</a> (controls)</li>
+          <li><a href="#controls_android.control.aeExposureCompensation">android.control.aeExposureCompensation</a> (controls)</li>
+          <li><a href="#controls_android.control.aeLock">android.control.aeLock</a> (controls)</li>
+          <li><a href="#controls_android.control.aeMode">android.control.aeMode</a> (controls)</li>
+          <li><a href="#controls_android.control.aeRegions">android.control.aeRegions</a> (controls)</li>
+          <li><a href="#controls_android.control.aeTargetFpsRange">android.control.aeTargetFpsRange</a> (controls)</li>
+          <li><a href="#controls_android.control.aePrecaptureTrigger">android.control.aePrecaptureTrigger</a> (controls)</li>
+          <li><a href="#controls_android.control.afMode">android.control.afMode</a> (controls)</li>
+          <li><a href="#controls_android.control.afRegions">android.control.afRegions</a> (controls)</li>
+          <li><a href="#controls_android.control.afTrigger">android.control.afTrigger</a> (controls)</li>
+          <li><a href="#controls_android.control.awbLock">android.control.awbLock</a> (controls)</li>
+          <li><a href="#controls_android.control.awbMode">android.control.awbMode</a> (controls)</li>
+          <li><a href="#controls_android.control.awbRegions">android.control.awbRegions</a> (controls)</li>
+          <li><a href="#controls_android.control.captureIntent">android.control.captureIntent</a> (controls)</li>
+          <li><a href="#controls_android.control.effectMode">android.control.effectMode</a> (controls)</li>
+          <li><a href="#controls_android.control.mode">android.control.mode</a> (controls)</li>
+          <li><a href="#controls_android.control.sceneMode">android.control.sceneMode</a> (controls)</li>
+          <li><a href="#controls_android.control.videoStabilizationMode">android.control.videoStabilizationMode</a> (controls)</li>
+          <li><a href="#static_android.control.aeAvailableAntibandingModes">android.control.aeAvailableAntibandingModes</a> (static)</li>
+          <li><a href="#static_android.control.aeAvailableModes">android.control.aeAvailableModes</a> (static)</li>
+          <li><a href="#static_android.control.aeAvailableTargetFpsRanges">android.control.aeAvailableTargetFpsRanges</a> (static)</li>
+          <li><a href="#static_android.control.aeCompensationRange">android.control.aeCompensationRange</a> (static)</li>
+          <li><a href="#static_android.control.aeCompensationStep">android.control.aeCompensationStep</a> (static)</li>
+          <li><a href="#static_android.control.afAvailableModes">android.control.afAvailableModes</a> (static)</li>
+          <li><a href="#static_android.control.availableEffects">android.control.availableEffects</a> (static)</li>
+          <li><a href="#static_android.control.availableSceneModes">android.control.availableSceneModes</a> (static)</li>
+          <li><a href="#static_android.control.availableVideoStabilizationModes">android.control.availableVideoStabilizationModes</a> (static)</li>
+          <li><a href="#static_android.control.awbAvailableModes">android.control.awbAvailableModes</a> (static)</li>
+          <li><a href="#static_android.control.maxRegions">android.control.maxRegions</a> (static)</li>
+          <li><a href="#static_android.control.sceneModeOverrides">android.control.sceneModeOverrides</a> (static)</li>
+          <li><a href="#static_android.control.aeLockAvailable">android.control.aeLockAvailable</a> (static)</li>
+          <li><a href="#static_android.control.awbLockAvailable">android.control.awbLockAvailable</a> (static)</li>
+          <li><a href="#controls_android.flash.mode">android.flash.mode</a> (controls)</li>
+          <li><a href="#static_android.flash.info.available">android.flash.info.available</a> (static)</li>
+          <li><a href="#controls_android.jpeg.gpsCoordinates">android.jpeg.gpsCoordinates</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.gpsProcessingMethod">android.jpeg.gpsProcessingMethod</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.gpsTimestamp">android.jpeg.gpsTimestamp</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.orientation">android.jpeg.orientation</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.quality">android.jpeg.quality</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.thumbnailQuality">android.jpeg.thumbnailQuality</a> (controls)</li>
+          <li><a href="#controls_android.jpeg.thumbnailSize">android.jpeg.thumbnailSize</a> (controls)</li>
+          <li><a href="#static_android.jpeg.availableThumbnailSizes">android.jpeg.availableThumbnailSizes</a> (static)</li>
+          <li><a href="#controls_android.lens.focusDistance">android.lens.focusDistance</a> (controls)</li>
+          <li><a href="#static_android.lens.info.availableFocalLengths">android.lens.info.availableFocalLengths</a> (static)</li>
+          <li><a href="#dynamic_android.lens.focusRange">android.lens.focusRange</a> (dynamic)</li>
+          <li><a href="#static_android.request.maxNumOutputStreams">android.request.maxNumOutputStreams</a> (static)</li>
+          <li><a href="#controls_android.scaler.cropRegion">android.scaler.cropRegion</a> (controls)</li>
+          <li><a href="#static_android.scaler.availableFormats">android.scaler.availableFormats</a> (static)</li>
+          <li><a href="#static_android.scaler.availableJpegMinDurations">android.scaler.availableJpegMinDurations</a> (static)</li>
+          <li><a href="#static_android.scaler.availableJpegSizes">android.scaler.availableJpegSizes</a> (static)</li>
+          <li><a href="#static_android.scaler.availableMaxDigitalZoom">android.scaler.availableMaxDigitalZoom</a> (static)</li>
+          <li><a href="#static_android.scaler.availableProcessedMinDurations">android.scaler.availableProcessedMinDurations</a> (static)</li>
+          <li><a href="#static_android.scaler.availableProcessedSizes">android.scaler.availableProcessedSizes</a> (static)</li>
+          <li><a href="#static_android.scaler.availableRawMinDurations">android.scaler.availableRawMinDurations</a> (static)</li>
+          <li><a href="#static_android.sensor.info.sensitivityRange">android.sensor.info.sensitivityRange</a> (static)</li>
+          <li><a href="#static_android.sensor.info.physicalSize">android.sensor.info.physicalSize</a> (static)</li>
+          <li><a href="#static_android.sensor.info.pixelArraySize">android.sensor.info.pixelArraySize</a> (static)</li>
+          <li><a href="#static_android.sensor.orientation">android.sensor.orientation</a> (static)</li>
+          <li><a href="#dynamic_android.sensor.timestamp">android.sensor.timestamp</a> (dynamic)</li>
+          <li><a href="#controls_android.statistics.faceDetectMode">android.statistics.faceDetectMode</a> (controls)</li>
+          <li><a href="#static_android.statistics.info.maxFaceCount">android.statistics.info.maxFaceCount</a> (static)</li>
+          <li><a href="#dynamic_android.statistics.faceIds">android.statistics.faceIds</a> (dynamic)</li>
+          <li><a href="#dynamic_android.statistics.faceLandmarks">android.statistics.faceLandmarks</a> (dynamic)</li>
+          <li><a href="#dynamic_android.statistics.faceRectangles">android.statistics.faceRectangles</a> (dynamic)</li>
+          <li><a href="#dynamic_android.statistics.faceScores">android.statistics.faceScores</a> (dynamic)</li>
+          <li><a href="#dynamic_android.lens.focalLength">android.lens.focalLength</a> (dynamic)</li>
+          <li><a href="#dynamic_android.lens.focusDistance">android.lens.focusDistance</a> (dynamic)</li>
+        </ul>
+      </li> <!-- tag_BC -->
+      <li id="tag_V1">V1 - 
+        New features for first camera 2 release (API1)
+    
+        <ul class="tags_entries">
+          <li><a href="#static_android.colorCorrection.availableAberrationModes">android.colorCorrection.availableAberrationModes</a> (static)</li>
+          <li><a href="#static_android.control.availableHighSpeedVideoConfigurations">android.control.availableHighSpeedVideoConfigurations</a> (static)</li>
+          <li><a href="#controls_android.edge.mode">android.edge.mode</a> (controls)</li>
+          <li><a href="#static_android.edge.availableEdgeModes">android.edge.availableEdgeModes</a> (static)</li>
+          <li><a href="#controls_android.hotPixel.mode">android.hotPixel.mode</a> (controls)</li>
+          <li><a href="#static_android.hotPixel.availableHotPixelModes">android.hotPixel.availableHotPixelModes</a> (static)</li>
+          <li><a href="#controls_android.lens.aperture">android.lens.aperture</a> (controls)</li>
+          <li><a href="#controls_android.lens.filterDensity">android.lens.filterDensity</a> (controls)</li>
+          <li><a href="#controls_android.lens.focalLength">android.lens.focalLength</a> (controls)</li>
+          <li><a href="#controls_android.lens.focusDistance">android.lens.focusDistance</a> (controls)</li>
+          <li><a href="#controls_android.lens.opticalStabilizationMode">android.lens.opticalStabilizationMode</a> (controls)</li>
+          <li><a href="#static_android.lens.info.availableApertures">android.lens.info.availableApertures</a> (static)</li>
+          <li><a href="#static_android.lens.info.availableFilterDensities">android.lens.info.availableFilterDensities</a> (static)</li>
+          <li><a href="#static_android.lens.info.availableFocalLengths">android.lens.info.availableFocalLengths</a> (static)</li>
+          <li><a href="#static_android.lens.info.availableOpticalStabilization">android.lens.info.availableOpticalStabilization</a> (static)</li>
+          <li><a href="#static_android.lens.info.minimumFocusDistance">android.lens.info.minimumFocusDistance</a> (static)</li>
+          <li><a href="#static_android.lens.info.shadingMapSize">android.lens.info.shadingMapSize</a> (static)</li>
+          <li><a href="#static_android.lens.info.focusDistanceCalibration">android.lens.info.focusDistanceCalibration</a> (static)</li>
+          <li><a href="#dynamic_android.lens.state">android.lens.state</a> (dynamic)</li>
+          <li><a href="#controls_android.noiseReduction.mode">android.noiseReduction.mode</a> (controls)</li>
+          <li><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.noiseReduction.availableNoiseReductionModes</a> (static)</li>
+          <li><a href="#controls_android.request.id">android.request.id</a> (controls)</li>
+          <li><a href="#static_android.scaler.availableMinFrameDurations">android.scaler.availableMinFrameDurations</a> (static)</li>
+          <li><a href="#static_android.scaler.availableStallDurations">android.scaler.availableStallDurations</a> (static)</li>
+          <li><a href="#controls_android.sensor.exposureTime">android.sensor.exposureTime</a> (controls)</li>
+          <li><a href="#controls_android.sensor.frameDuration">android.sensor.frameDuration</a> (controls)</li>
+          <li><a href="#controls_android.sensor.sensitivity">android.sensor.sensitivity</a> (controls)</li>
+          <li><a href="#static_android.sensor.info.sensitivityRange">android.sensor.info.sensitivityRange</a> (static)</li>
+          <li><a href="#static_android.sensor.info.exposureTimeRange">android.sensor.info.exposureTimeRange</a> (static)</li>
+          <li><a href="#static_android.sensor.info.maxFrameDuration">android.sensor.info.maxFrameDuration</a> (static)</li>
+          <li><a href="#static_android.sensor.info.physicalSize">android.sensor.info.physicalSize</a> (static)</li>
+          <li><a href="#static_android.sensor.info.timestampSource">android.sensor.info.timestampSource</a> (static)</li>
+          <li><a href="#static_android.sensor.maxAnalogSensitivity">android.sensor.maxAnalogSensitivity</a> (static)</li>
+          <li><a href="#dynamic_android.sensor.rollingShutterSkew">android.sensor.rollingShutterSkew</a> (dynamic)</li>
+          <li><a href="#controls_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a> (controls)</li>
+          <li><a href="#static_android.statistics.info.availableHotPixelMapModes">android.statistics.info.availableHotPixelMapModes</a> (static)</li>
+          <li><a href="#dynamic_android.statistics.hotPixelMap">android.statistics.hotPixelMap</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sync.frameNumber">android.sync.frameNumber</a> (dynamic)</li>
+          <li><a href="#static_android.sync.maxLatency">android.sync.maxLatency</a> (static)</li>
+          <li><a href="#dynamic_android.edge.mode">android.edge.mode</a> (dynamic)</li>
+          <li><a href="#dynamic_android.hotPixel.mode">android.hotPixel.mode</a> (dynamic)</li>
+          <li><a href="#dynamic_android.lens.aperture">android.lens.aperture</a> (dynamic)</li>
+          <li><a href="#dynamic_android.lens.filterDensity">android.lens.filterDensity</a> (dynamic)</li>
+          <li><a href="#dynamic_android.lens.opticalStabilizationMode">android.lens.opticalStabilizationMode</a> (dynamic)</li>
+          <li><a href="#dynamic_android.noiseReduction.mode">android.noiseReduction.mode</a> (dynamic)</li>
+        </ul>
+      </li> <!-- tag_V1 -->
+      <li id="tag_RAW">RAW - 
+        Needed for useful RAW image processing and DNG file support
+    
+        <ul class="tags_entries">
+          <li><a href="#controls_android.hotPixel.mode">android.hotPixel.mode</a> (controls)</li>
+          <li><a href="#static_android.hotPixel.availableHotPixelModes">android.hotPixel.availableHotPixelModes</a> (static)</li>
+          <li><a href="#static_android.sensor.info.activeArraySize">android.sensor.info.activeArraySize</a> (static)</li>
+          <li><a href="#static_android.sensor.info.colorFilterArrangement">android.sensor.info.colorFilterArrangement</a> (static)</li>
+          <li><a href="#static_android.sensor.info.pixelArraySize">android.sensor.info.pixelArraySize</a> (static)</li>
+          <li><a href="#static_android.sensor.info.whiteLevel">android.sensor.info.whiteLevel</a> (static)</li>
+          <li><a href="#static_android.sensor.info.preCorrectionActiveArraySize">android.sensor.info.preCorrectionActiveArraySize</a> (static)</li>
+          <li><a href="#static_android.sensor.referenceIlluminant1">android.sensor.referenceIlluminant1</a> (static)</li>
+          <li><a href="#static_android.sensor.referenceIlluminant2">android.sensor.referenceIlluminant2</a> (static)</li>
+          <li><a href="#static_android.sensor.calibrationTransform1">android.sensor.calibrationTransform1</a> (static)</li>
+          <li><a href="#static_android.sensor.calibrationTransform2">android.sensor.calibrationTransform2</a> (static)</li>
+          <li><a href="#static_android.sensor.colorTransform1">android.sensor.colorTransform1</a> (static)</li>
+          <li><a href="#static_android.sensor.colorTransform2">android.sensor.colorTransform2</a> (static)</li>
+          <li><a href="#static_android.sensor.forwardMatrix1">android.sensor.forwardMatrix1</a> (static)</li>
+          <li><a href="#static_android.sensor.forwardMatrix2">android.sensor.forwardMatrix2</a> (static)</li>
+          <li><a href="#static_android.sensor.blackLevelPattern">android.sensor.blackLevelPattern</a> (static)</li>
+          <li><a href="#static_android.sensor.profileHueSatMapDimensions">android.sensor.profileHueSatMapDimensions</a> (static)</li>
+          <li><a href="#dynamic_android.sensor.neutralColorPoint">android.sensor.neutralColorPoint</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.noiseProfile">android.sensor.noiseProfile</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.profileHueSatMap">android.sensor.profileHueSatMap</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.profileToneCurve">android.sensor.profileToneCurve</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.greenSplit">android.sensor.greenSplit</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.dynamicBlackLevel">android.sensor.dynamicBlackLevel</a> (dynamic)</li>
+          <li><a href="#dynamic_android.sensor.dynamicWhiteLevel">android.sensor.dynamicWhiteLevel</a> (dynamic)</li>
+          <li><a href="#controls_android.statistics.hotPixelMapMode">android.statistics.hotPixelMapMode</a> (controls)</li>
+          <li><a href="#static_android.statistics.info.availableHotPixelMapModes">android.statistics.info.availableHotPixelMapModes</a> (static)</li>
+          <li><a href="#dynamic_android.statistics.hotPixelMap">android.statistics.hotPixelMap</a> (dynamic)</li>
+          <li><a href="#controls_android.statistics.lensShadingMapMode">android.statistics.lensShadingMapMode</a> (controls)</li>
+          <li><a href="#dynamic_android.hotPixel.mode">android.hotPixel.mode</a> (dynamic)</li>
+        </ul>
+      </li> <!-- tag_RAW -->
+      <li id="tag_HAL2">HAL2 - 
+        Entry is only used by camera device HAL 2.x
+    
+        <ul class="tags_entries">
+          <li><a href="#controls_android.request.inputStreams">android.request.inputStreams</a> (controls)</li>
+          <li><a href="#controls_android.request.outputStreams">android.request.outputStreams</a> (controls)</li>
+          <li><a href="#controls_android.request.type">android.request.type</a> (controls)</li>
+          <li><a href="#static_android.request.maxNumReprocessStreams">android.request.maxNumReprocessStreams</a> (static)</li>
+          <li><a href="#controls_android.blackLevel.lock">android.blackLevel.lock</a> (controls)</li>
+        </ul>
+      </li> <!-- tag_HAL2 -->
+      <li id="tag_FULL">FULL - 
+        Entry is required for full hardware level devices, and optional for other hardware levels
+    
+        <ul class="tags_entries">
+          <li><a href="#static_android.sensor.maxAnalogSensitivity">android.sensor.maxAnalogSensitivity</a> (static)</li>
+        </ul>
+      </li> <!-- tag_FULL -->
+      <li id="tag_DEPTH">DEPTH - 
+        Entry is required for the depth capability.
+    
+        <ul class="tags_entries">
+          <li><a href="#static_android.lens.poseRotation">android.lens.poseRotation</a> (static)</li>
+          <li><a href="#static_android.lens.poseTranslation">android.lens.poseTranslation</a> (static)</li>
+          <li><a href="#static_android.lens.intrinsicCalibration">android.lens.intrinsicCalibration</a> (static)</li>
+          <li><a href="#static_android.lens.radialDistortion">android.lens.radialDistortion</a> (static)</li>
+          <li><a href="#static_android.depth.maxDepthSamples">android.depth.maxDepthSamples</a> (static)</li>
+          <li><a href="#static_android.depth.availableDepthStreamConfigurations">android.depth.availableDepthStreamConfigurations</a> (static)</li>
+          <li><a href="#static_android.depth.availableDepthMinFrameDurations">android.depth.availableDepthMinFrameDurations</a> (static)</li>
+          <li><a href="#static_android.depth.availableDepthStallDurations">android.depth.availableDepthStallDurations</a> (static)</li>
+        </ul>
+      </li> <!-- tag_DEPTH -->
+      <li id="tag_REPROC">REPROC - 
+        Entry is required for the YUV or PRIVATE reprocessing capability.
+    
+        <ul class="tags_entries">
+          <li><a href="#controls_android.edge.mode">android.edge.mode</a> (controls)</li>
+          <li><a href="#static_android.edge.availableEdgeModes">android.edge.availableEdgeModes</a> (static)</li>
+          <li><a href="#controls_android.noiseReduction.mode">android.noiseReduction.mode</a> (controls)</li>
+          <li><a href="#static_android.noiseReduction.availableNoiseReductionModes">android.noiseReduction.availableNoiseReductionModes</a> (static)</li>
+          <li><a href="#static_android.request.maxNumInputStreams">android.request.maxNumInputStreams</a> (static)</li>
+          <li><a href="#static_android.scaler.availableInputOutputFormatsMap">android.scaler.availableInputOutputFormatsMap</a> (static)</li>
+          <li><a href="#controls_android.reprocess.effectiveExposureFactor">android.reprocess.effectiveExposureFactor</a> (controls)</li>
+          <li><a href="#static_android.reprocess.maxCaptureStall">android.reprocess.maxCaptureStall</a> (static)</li>
+          <li><a href="#dynamic_android.edge.mode">android.edge.mode</a> (dynamic)</li>
+          <li><a href="#dynamic_android.noiseReduction.mode">android.noiseReduction.mode</a> (dynamic)</li>
+        </ul>
+      </li> <!-- tag_REPROC -->
+      <li id="tag_FUTURE">FUTURE - 
+        Entry is  under-specified and is not required for now. This is for book-keeping purpose,
+        do not implement or use it, it may be revised for future.
+    
+        <ul class="tags_entries">
+          <li><a href="#controls_android.demosaic.mode">android.demosaic.mode</a> (controls)</li>
+          <li><a href="#controls_android.edge.strength">android.edge.strength</a> (controls)</li>
+          <li><a href="#controls_android.flash.firingPower">android.flash.firingPower</a> (controls)</li>
+          <li><a href="#controls_android.flash.firingTime">android.flash.firingTime</a> (controls)</li>
+          <li><a href="#static_android.flash.info.chargeDuration">android.flash.info.chargeDuration</a> (static)</li>
+          <li><a href="#static_android.flash.colorTemperature">android.flash.colorTemperature</a> (static)</li>
+          <li><a href="#static_android.flash.maxEnergy">android.flash.maxEnergy</a> (static)</li>
+          <li><a href="#dynamic_android.jpeg.size">android.jpeg.size</a> (dynamic)</li>
+          <li><a href="#controls_android.noiseReduction.strength">android.noiseReduction.strength</a> (controls)</li>
+          <li><a href="#controls_android.request.metadataMode">android.request.metadataMode</a> (controls)</li>
+          <li><a href="#static_android.sensor.baseGainFactor">android.sensor.baseGainFactor</a> (static)</li>
+          <li><a href="#dynamic_android.sensor.temperature">android.sensor.temperature</a> (dynamic)</li>
+          <li><a href="#controls_android.shading.strength">android.shading.strength</a> (controls)</li>
+          <li><a href="#controls_android.statistics.histogramMode">android.statistics.histogramMode</a> (controls)</li>
+          <li><a href="#controls_android.statistics.sharpnessMapMode">android.statistics.sharpnessMapMode</a> (controls)</li>
+          <li><a href="#static_android.statistics.info.histogramBucketCount">android.statistics.info.histogramBucketCount</a> (static)</li>
+          <li><a href="#static_android.statistics.info.maxHistogramCount">android.statistics.info.maxHistogramCount</a> (static)</li>
+          <li><a href="#static_android.statistics.info.maxSharpnessMapValue">android.statistics.info.maxSharpnessMapValue</a> (static)</li>
+          <li><a href="#static_android.statistics.info.sharpnessMapSize">android.statistics.info.sharpnessMapSize</a> (static)</li>
+          <li><a href="#dynamic_android.statistics.histogram">android.statistics.histogram</a> (dynamic)</li>
+          <li><a href="#dynamic_android.statistics.sharpnessMap">android.statistics.sharpnessMap</a> (dynamic)</li>
+        </ul>
+      </li> <!-- tag_FUTURE -->
+    </ul>
+  </div>
+
+  [ <a href="#">top</a> ]
+
+</body>
+</html>
diff --git a/camera/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal
new file mode 100644
index 0000000..ae70550
--- /dev/null
+++ b/camera/metadata/3.2/types.hal
@@ -0,0 +1,1316 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.metadata@3.2;
+
+/** TODO(b/33012412):
+ *   - The following information should be code-generated from:
+ *     system/media/camera/docs/metadata_properties.xml
+ *   - Some enum below should be signed:
+ *       - metadata section/key should be unsigned
+ *       - matadata value enum should be signed
+ */
+
+/**
+ * Top level hierarchy definitions for camera metadata. *_INFO sections are for
+ * the static metadata that can be retrived without opening the camera device.
+ * New sections must be added right before ANDROID_SECTION_COUNT to maintain
+ * existing enumerations.
+ */
+enum CameraMetadataSection : uint32_t {
+    ANDROID_COLOR_CORRECTION,
+
+    ANDROID_CONTROL,
+
+    ANDROID_DEMOSAIC,
+
+    ANDROID_EDGE,
+
+    ANDROID_FLASH,
+
+    ANDROID_FLASH_INFO,
+
+    ANDROID_HOT_PIXEL,
+
+    ANDROID_JPEG,
+
+    ANDROID_LENS,
+
+    ANDROID_LENS_INFO,
+
+    ANDROID_NOISE_REDUCTION,
+
+    ANDROID_QUIRKS,
+
+    ANDROID_REQUEST,
+
+    ANDROID_SCALER,
+
+    ANDROID_SENSOR,
+
+    ANDROID_SENSOR_INFO,
+
+    ANDROID_SHADING,
+
+    ANDROID_STATISTICS,
+
+    ANDROID_STATISTICS_INFO,
+
+    ANDROID_TONEMAP,
+
+    ANDROID_LED,
+
+    ANDROID_INFO,
+
+    ANDROID_BLACK_LEVEL,
+
+    ANDROID_SYNC,
+
+    ANDROID_REPROCESS,
+
+    ANDROID_DEPTH,
+
+    ANDROID_SECTION_COUNT,
+
+    VENDOR_SECTION = 0x8000,
+
+};
+
+/**
+ * Hierarchy positions in enum space. All vendor extension tags must be
+ * defined with tag >= VENDOR_SECTION_START
+ */
+enum CameraMetadataSectionStart : uint32_t {
+    ANDROID_COLOR_CORRECTION_START = CameraMetadataSection:ANDROID_COLOR_CORRECTION << 16,
+
+    ANDROID_CONTROL_START = CameraMetadataSection:ANDROID_CONTROL << 16,
+
+    ANDROID_DEMOSAIC_START = CameraMetadataSection:ANDROID_DEMOSAIC << 16,
+
+    ANDROID_EDGE_START = CameraMetadataSection:ANDROID_EDGE << 16,
+
+    ANDROID_FLASH_START = CameraMetadataSection:ANDROID_FLASH << 16,
+
+    ANDROID_FLASH_INFO_START = CameraMetadataSection:ANDROID_FLASH_INFO << 16,
+
+    ANDROID_HOT_PIXEL_START = CameraMetadataSection:ANDROID_HOT_PIXEL << 16,
+
+    ANDROID_JPEG_START = CameraMetadataSection:ANDROID_JPEG << 16,
+
+    ANDROID_LENS_START = CameraMetadataSection:ANDROID_LENS << 16,
+
+    ANDROID_LENS_INFO_START = CameraMetadataSection:ANDROID_LENS_INFO << 16,
+
+    ANDROID_NOISE_REDUCTION_START = CameraMetadataSection:ANDROID_NOISE_REDUCTION << 16,
+
+    ANDROID_QUIRKS_START = CameraMetadataSection:ANDROID_QUIRKS << 16,
+
+    ANDROID_REQUEST_START = CameraMetadataSection:ANDROID_REQUEST << 16,
+
+    ANDROID_SCALER_START = CameraMetadataSection:ANDROID_SCALER << 16,
+
+    ANDROID_SENSOR_START = CameraMetadataSection:ANDROID_SENSOR << 16,
+
+    ANDROID_SENSOR_INFO_START = CameraMetadataSection:ANDROID_SENSOR_INFO << 16,
+
+    ANDROID_SHADING_START = CameraMetadataSection:ANDROID_SHADING << 16,
+
+    ANDROID_STATISTICS_START = CameraMetadataSection:ANDROID_STATISTICS << 16,
+
+    ANDROID_STATISTICS_INFO_START = CameraMetadataSection:ANDROID_STATISTICS_INFO << 16,
+
+    ANDROID_TONEMAP_START = CameraMetadataSection:ANDROID_TONEMAP << 16,
+
+    ANDROID_LED_START = CameraMetadataSection:ANDROID_LED << 16,
+
+    ANDROID_INFO_START = CameraMetadataSection:ANDROID_INFO << 16,
+
+    ANDROID_BLACK_LEVEL_START = CameraMetadataSection:ANDROID_BLACK_LEVEL << 16,
+
+    ANDROID_SYNC_START = CameraMetadataSection:ANDROID_SYNC << 16,
+
+    ANDROID_REPROCESS_START = CameraMetadataSection:ANDROID_REPROCESS << 16,
+
+    ANDROID_DEPTH_START = CameraMetadataSection:ANDROID_DEPTH << 16,
+
+    VENDOR_SECTION_START = CameraMetadataSection:VENDOR_SECTION << 16,
+
+};
+
+/**
+ * Main enum for defining camera metadata tags. New entries must always go
+ * before the section _END tag to preserve existing enumeration values. In
+ * addition, the name and type of the tag needs to be added to
+ * system/media/camera/src/camera_metadata_tag_info.c
+ */
+enum CameraMetadataTag : uint32_t {
+    ANDROID_COLOR_CORRECTION_MODE = CameraMetadataSectionStart:ANDROID_COLOR_CORRECTION_START,
+
+    ANDROID_COLOR_CORRECTION_TRANSFORM,
+
+    ANDROID_COLOR_CORRECTION_GAINS,
+
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
+
+    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
+
+    ANDROID_COLOR_CORRECTION_END,
+
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE = CameraMetadataSectionStart:ANDROID_CONTROL_START,
+
+    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
+
+    ANDROID_CONTROL_AE_LOCK,
+
+    ANDROID_CONTROL_AE_MODE,
+
+    ANDROID_CONTROL_AE_REGIONS,
+
+    ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
+
+    ANDROID_CONTROL_AF_MODE,
+
+    ANDROID_CONTROL_AF_REGIONS,
+
+    ANDROID_CONTROL_AF_TRIGGER,
+
+    ANDROID_CONTROL_AWB_LOCK,
+
+    ANDROID_CONTROL_AWB_MODE,
+
+    ANDROID_CONTROL_AWB_REGIONS,
+
+    ANDROID_CONTROL_CAPTURE_INTENT,
+
+    ANDROID_CONTROL_EFFECT_MODE,
+
+    ANDROID_CONTROL_MODE,
+
+    ANDROID_CONTROL_SCENE_MODE,
+
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+
+    ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+
+    ANDROID_CONTROL_AE_AVAILABLE_MODES,
+
+    ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+
+    ANDROID_CONTROL_AE_COMPENSATION_RANGE,
+
+    ANDROID_CONTROL_AE_COMPENSATION_STEP,
+
+    ANDROID_CONTROL_AF_AVAILABLE_MODES,
+
+    ANDROID_CONTROL_AVAILABLE_EFFECTS,
+
+    ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
+
+    ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
+
+    ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+
+    ANDROID_CONTROL_MAX_REGIONS,
+
+    ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
+
+    ANDROID_CONTROL_AE_PRECAPTURE_ID,
+
+    ANDROID_CONTROL_AE_STATE,
+
+    ANDROID_CONTROL_AF_STATE,
+
+    ANDROID_CONTROL_AF_TRIGGER_ID,
+
+    ANDROID_CONTROL_AWB_STATE,
+
+    ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
+
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE,
+
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
+
+    ANDROID_CONTROL_AVAILABLE_MODES,
+
+    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
+
+    ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
+
+    ANDROID_CONTROL_END,
+
+    ANDROID_DEMOSAIC_MODE = CameraMetadataSectionStart:ANDROID_DEMOSAIC_START,
+
+    ANDROID_DEMOSAIC_END,
+
+    ANDROID_EDGE_MODE = CameraMetadataSectionStart:ANDROID_EDGE_START,
+
+    ANDROID_EDGE_STRENGTH,
+
+    ANDROID_EDGE_AVAILABLE_EDGE_MODES,
+
+    ANDROID_EDGE_END,
+
+    ANDROID_FLASH_FIRING_POWER = CameraMetadataSectionStart:ANDROID_FLASH_START,
+
+    ANDROID_FLASH_FIRING_TIME,
+
+    ANDROID_FLASH_MODE,
+
+    ANDROID_FLASH_COLOR_TEMPERATURE,
+
+    ANDROID_FLASH_MAX_ENERGY,
+
+    ANDROID_FLASH_STATE,
+
+    ANDROID_FLASH_END,
+
+    ANDROID_FLASH_INFO_AVAILABLE = CameraMetadataSectionStart:ANDROID_FLASH_INFO_START,
+
+    ANDROID_FLASH_INFO_CHARGE_DURATION,
+
+    ANDROID_FLASH_INFO_END,
+
+    ANDROID_HOT_PIXEL_MODE = CameraMetadataSectionStart:ANDROID_HOT_PIXEL_START,
+
+    ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
+
+    ANDROID_HOT_PIXEL_END,
+
+    ANDROID_JPEG_GPS_COORDINATES = CameraMetadataSectionStart:ANDROID_JPEG_START,
+
+    ANDROID_JPEG_GPS_PROCESSING_METHOD,
+
+    ANDROID_JPEG_GPS_TIMESTAMP,
+
+    ANDROID_JPEG_ORIENTATION,
+
+    ANDROID_JPEG_QUALITY,
+
+    ANDROID_JPEG_THUMBNAIL_QUALITY,
+
+    ANDROID_JPEG_THUMBNAIL_SIZE,
+
+    ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
+
+    ANDROID_JPEG_MAX_SIZE,
+
+    ANDROID_JPEG_SIZE,
+
+    ANDROID_JPEG_END,
+
+    ANDROID_LENS_APERTURE = CameraMetadataSectionStart:ANDROID_LENS_START,
+
+    ANDROID_LENS_FILTER_DENSITY,
+
+    ANDROID_LENS_FOCAL_LENGTH,
+
+    ANDROID_LENS_FOCUS_DISTANCE,
+
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+
+    ANDROID_LENS_FACING,
+
+    ANDROID_LENS_POSE_ROTATION,
+
+    ANDROID_LENS_POSE_TRANSLATION,
+
+    ANDROID_LENS_FOCUS_RANGE,
+
+    ANDROID_LENS_STATE,
+
+    ANDROID_LENS_INTRINSIC_CALIBRATION,
+
+    ANDROID_LENS_RADIAL_DISTORTION,
+
+    ANDROID_LENS_END,
+
+    ANDROID_LENS_INFO_AVAILABLE_APERTURES = CameraMetadataSectionStart:ANDROID_LENS_INFO_START,
+
+    ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
+
+    ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
+
+    ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
+
+    ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
+
+    ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
+
+    ANDROID_LENS_INFO_SHADING_MAP_SIZE,
+
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
+
+    ANDROID_LENS_INFO_END,
+
+    ANDROID_NOISE_REDUCTION_MODE = CameraMetadataSectionStart:ANDROID_NOISE_REDUCTION_START,
+
+    ANDROID_NOISE_REDUCTION_STRENGTH,
+
+    ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
+
+    ANDROID_NOISE_REDUCTION_END,
+
+    ANDROID_QUIRKS_METERING_CROP_REGION = CameraMetadataSectionStart:ANDROID_QUIRKS_START,
+
+    ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO,
+
+    ANDROID_QUIRKS_USE_ZSL_FORMAT,
+
+    ANDROID_QUIRKS_USE_PARTIAL_RESULT,
+
+    ANDROID_QUIRKS_PARTIAL_RESULT,
+
+    ANDROID_QUIRKS_END,
+
+    ANDROID_REQUEST_FRAME_COUNT = CameraMetadataSectionStart:ANDROID_REQUEST_START,
+
+    ANDROID_REQUEST_ID,
+
+    ANDROID_REQUEST_INPUT_STREAMS,
+
+    ANDROID_REQUEST_METADATA_MODE,
+
+    ANDROID_REQUEST_OUTPUT_STREAMS,
+
+    ANDROID_REQUEST_TYPE,
+
+    ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
+
+    ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS,
+
+    ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
+
+    ANDROID_REQUEST_PIPELINE_DEPTH,
+
+    ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
+
+    ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+
+    ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
+
+    ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
+
+    ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
+
+    ANDROID_REQUEST_END,
+
+    ANDROID_SCALER_CROP_REGION = CameraMetadataSectionStart:ANDROID_SCALER_START,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS,
+
+    ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
+
+    ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
+
+    ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
+
+    ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
+
+    ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
+
+    ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
+
+    ANDROID_SCALER_AVAILABLE_RAW_SIZES,
+
+    ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP,
+
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
+
+    ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+
+    ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
+
+    ANDROID_SCALER_CROPPING_TYPE,
+
+    ANDROID_SCALER_END,
+
+    ANDROID_SENSOR_EXPOSURE_TIME = CameraMetadataSectionStart:ANDROID_SENSOR_START,
+
+    ANDROID_SENSOR_FRAME_DURATION,
+
+    ANDROID_SENSOR_SENSITIVITY,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
+
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
+
+    ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
+
+    ANDROID_SENSOR_COLOR_TRANSFORM1,
+
+    ANDROID_SENSOR_COLOR_TRANSFORM2,
+
+    ANDROID_SENSOR_FORWARD_MATRIX1,
+
+    ANDROID_SENSOR_FORWARD_MATRIX2,
+
+    ANDROID_SENSOR_BASE_GAIN_FACTOR,
+
+    ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+
+    ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+
+    ANDROID_SENSOR_ORIENTATION,
+
+    ANDROID_SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS,
+
+    ANDROID_SENSOR_TIMESTAMP,
+
+    ANDROID_SENSOR_TEMPERATURE,
+
+    ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
+
+    ANDROID_SENSOR_NOISE_PROFILE,
+
+    ANDROID_SENSOR_PROFILE_HUE_SAT_MAP,
+
+    ANDROID_SENSOR_PROFILE_TONE_CURVE,
+
+    ANDROID_SENSOR_GREEN_SPLIT,
+
+    ANDROID_SENSOR_TEST_PATTERN_DATA,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE,
+
+    ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
+
+    ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
+
+    ANDROID_SENSOR_OPTICAL_BLACK_REGIONS,
+
+    ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL,
+
+    ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL,
+
+    ANDROID_SENSOR_OPAQUE_RAW_SIZE,
+
+    ANDROID_SENSOR_END,
+
+    ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE = CameraMetadataSectionStart:ANDROID_SENSOR_INFO_START,
+
+    ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
+
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
+
+    ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
+
+    ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
+
+    ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
+
+    ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
+
+    ANDROID_SENSOR_INFO_WHITE_LEVEL,
+
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
+
+    ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED,
+
+    ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+
+    ANDROID_SENSOR_INFO_END,
+
+    ANDROID_SHADING_MODE = CameraMetadataSectionStart:ANDROID_SHADING_START,
+
+    ANDROID_SHADING_STRENGTH,
+
+    ANDROID_SHADING_AVAILABLE_MODES,
+
+    ANDROID_SHADING_END,
+
+    ANDROID_STATISTICS_FACE_DETECT_MODE = CameraMetadataSectionStart:ANDROID_STATISTICS_START,
+
+    ANDROID_STATISTICS_HISTOGRAM_MODE,
+
+    ANDROID_STATISTICS_SHARPNESS_MAP_MODE,
+
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
+
+    ANDROID_STATISTICS_FACE_IDS,
+
+    ANDROID_STATISTICS_FACE_LANDMARKS,
+
+    ANDROID_STATISTICS_FACE_RECTANGLES,
+
+    ANDROID_STATISTICS_FACE_SCORES,
+
+    ANDROID_STATISTICS_HISTOGRAM,
+
+    ANDROID_STATISTICS_SHARPNESS_MAP,
+
+    ANDROID_STATISTICS_LENS_SHADING_CORRECTION_MAP,
+
+    ANDROID_STATISTICS_LENS_SHADING_MAP,
+
+    ANDROID_STATISTICS_PREDICTED_COLOR_GAINS,
+
+    ANDROID_STATISTICS_PREDICTED_COLOR_TRANSFORM,
+
+    ANDROID_STATISTICS_SCENE_FLICKER,
+
+    ANDROID_STATISTICS_HOT_PIXEL_MAP,
+
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
+
+    ANDROID_STATISTICS_END,
+
+    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES =
+            CameraMetadataSectionStart:ANDROID_STATISTICS_INFO_START,
+
+    ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT,
+
+    ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
+
+    ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
+
+    ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
+
+    ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
+
+    ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
+
+    ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
+
+    ANDROID_STATISTICS_INFO_END,
+
+    ANDROID_TONEMAP_CURVE_BLUE = CameraMetadataSectionStart:ANDROID_TONEMAP_START,
+
+    ANDROID_TONEMAP_CURVE_GREEN,
+
+    ANDROID_TONEMAP_CURVE_RED,
+
+    ANDROID_TONEMAP_MODE,
+
+    ANDROID_TONEMAP_MAX_CURVE_POINTS,
+
+    ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
+
+    ANDROID_TONEMAP_GAMMA,
+
+    ANDROID_TONEMAP_PRESET_CURVE,
+
+    ANDROID_TONEMAP_END,
+
+    ANDROID_LED_TRANSMIT = CameraMetadataSectionStart:ANDROID_LED_START,
+
+    ANDROID_LED_AVAILABLE_LEDS,
+
+    ANDROID_LED_END,
+
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL = CameraMetadataSectionStart:ANDROID_INFO_START,
+
+    ANDROID_INFO_END,
+
+    ANDROID_BLACK_LEVEL_LOCK = CameraMetadataSectionStart:ANDROID_BLACK_LEVEL_START,
+
+    ANDROID_BLACK_LEVEL_END,
+
+    ANDROID_SYNC_FRAME_NUMBER = CameraMetadataSectionStart:ANDROID_SYNC_START,
+
+    ANDROID_SYNC_MAX_LATENCY,
+
+    ANDROID_SYNC_END,
+
+    ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR = CameraMetadataSectionStart:ANDROID_REPROCESS_START,
+
+    ANDROID_REPROCESS_MAX_CAPTURE_STALL,
+
+    ANDROID_REPROCESS_END,
+
+    ANDROID_DEPTH_MAX_DEPTH_SAMPLES = CameraMetadataSectionStart:ANDROID_DEPTH_START,
+
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
+
+    ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
+
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
+
+    ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
+
+    ANDROID_DEPTH_END,
+
+};
+
+/**
+ * Enumeration definitions for the various entries that need them
+ */
+enum CameraMetadataEnumAndroidColorCorrectionMode : uint32_t {
+    ANDROID_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX,
+
+    ANDROID_COLOR_CORRECTION_MODE_FAST,
+
+    ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY,
+
+};
+
+enum CameraMetadataEnumAndroidColorCorrectionAberrationMode : uint32_t {
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
+
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
+
+    ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY,
+
+};
+
+enum CameraMetadataEnumAndroidControlAeAntibandingMode : uint32_t {
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
+
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
+
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
+
+    ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
+
+};
+
+enum CameraMetadataEnumAndroidControlAeLock : uint32_t {
+    ANDROID_CONTROL_AE_LOCK_OFF,
+
+    ANDROID_CONTROL_AE_LOCK_ON,
+
+};
+
+enum CameraMetadataEnumAndroidControlAeMode : uint32_t {
+    ANDROID_CONTROL_AE_MODE_OFF,
+
+    ANDROID_CONTROL_AE_MODE_ON,
+
+    ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
+
+    ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
+
+    ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
+
+};
+
+enum CameraMetadataEnumAndroidControlAePrecaptureTrigger : uint32_t {
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE,
+
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START,
+
+    ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL,
+
+};
+
+enum CameraMetadataEnumAndroidControlAfMode : uint32_t {
+    ANDROID_CONTROL_AF_MODE_OFF,
+
+    ANDROID_CONTROL_AF_MODE_AUTO,
+
+    ANDROID_CONTROL_AF_MODE_MACRO,
+
+    ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
+
+    ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
+
+    ANDROID_CONTROL_AF_MODE_EDOF,
+
+};
+
+enum CameraMetadataEnumAndroidControlAfTrigger : uint32_t {
+    ANDROID_CONTROL_AF_TRIGGER_IDLE,
+
+    ANDROID_CONTROL_AF_TRIGGER_START,
+
+    ANDROID_CONTROL_AF_TRIGGER_CANCEL,
+
+};
+
+enum CameraMetadataEnumAndroidControlAwbLock : uint32_t {
+    ANDROID_CONTROL_AWB_LOCK_OFF,
+
+    ANDROID_CONTROL_AWB_LOCK_ON,
+
+};
+
+enum CameraMetadataEnumAndroidControlAwbMode : uint32_t {
+    ANDROID_CONTROL_AWB_MODE_OFF,
+
+    ANDROID_CONTROL_AWB_MODE_AUTO,
+
+    ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
+
+    ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
+
+    ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT,
+
+    ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
+
+    ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT,
+
+    ANDROID_CONTROL_AWB_MODE_TWILIGHT,
+
+    ANDROID_CONTROL_AWB_MODE_SHADE,
+
+};
+
+enum CameraMetadataEnumAndroidControlCaptureIntent : uint32_t {
+    ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
+
+    ANDROID_CONTROL_CAPTURE_INTENT_MANUAL,
+
+};
+
+enum CameraMetadataEnumAndroidControlEffectMode : uint32_t {
+    ANDROID_CONTROL_EFFECT_MODE_OFF,
+
+    ANDROID_CONTROL_EFFECT_MODE_MONO,
+
+    ANDROID_CONTROL_EFFECT_MODE_NEGATIVE,
+
+    ANDROID_CONTROL_EFFECT_MODE_SOLARIZE,
+
+    ANDROID_CONTROL_EFFECT_MODE_SEPIA,
+
+    ANDROID_CONTROL_EFFECT_MODE_POSTERIZE,
+
+    ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD,
+
+    ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD,
+
+    ANDROID_CONTROL_EFFECT_MODE_AQUA,
+
+};
+
+enum CameraMetadataEnumAndroidControlMode : uint32_t {
+    ANDROID_CONTROL_MODE_OFF,
+
+    ANDROID_CONTROL_MODE_AUTO,
+
+    ANDROID_CONTROL_MODE_USE_SCENE_MODE,
+
+    ANDROID_CONTROL_MODE_OFF_KEEP_STATE,
+
+};
+
+enum CameraMetadataEnumAndroidControlSceneMode : uint32_t {
+    ANDROID_CONTROL_SCENE_MODE_DISABLED = 0,
+
+    ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY,
+
+    ANDROID_CONTROL_SCENE_MODE_ACTION,
+
+    ANDROID_CONTROL_SCENE_MODE_PORTRAIT,
+
+    ANDROID_CONTROL_SCENE_MODE_LANDSCAPE,
+
+    ANDROID_CONTROL_SCENE_MODE_NIGHT,
+
+    ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
+
+    ANDROID_CONTROL_SCENE_MODE_THEATRE,
+
+    ANDROID_CONTROL_SCENE_MODE_BEACH,
+
+    ANDROID_CONTROL_SCENE_MODE_SNOW,
+
+    ANDROID_CONTROL_SCENE_MODE_SUNSET,
+
+    ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO,
+
+    ANDROID_CONTROL_SCENE_MODE_FIREWORKS,
+
+    ANDROID_CONTROL_SCENE_MODE_SPORTS,
+
+    ANDROID_CONTROL_SCENE_MODE_PARTY,
+
+    ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT,
+
+    ANDROID_CONTROL_SCENE_MODE_BARCODE,
+
+    ANDROID_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,
+
+    ANDROID_CONTROL_SCENE_MODE_HDR,
+
+    ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT,
+
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START = 100,
+
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END = 127,
+
+};
+
+enum CameraMetadataEnumAndroidControlVideoStabilizationMode : uint32_t {
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
+
+    ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidControlAeState : uint32_t {
+    ANDROID_CONTROL_AE_STATE_INACTIVE,
+
+    ANDROID_CONTROL_AE_STATE_SEARCHING,
+
+    ANDROID_CONTROL_AE_STATE_CONVERGED,
+
+    ANDROID_CONTROL_AE_STATE_LOCKED,
+
+    ANDROID_CONTROL_AE_STATE_FLASH_REQUIRED,
+
+    ANDROID_CONTROL_AE_STATE_PRECAPTURE,
+
+};
+
+enum CameraMetadataEnumAndroidControlAfState : uint32_t {
+    ANDROID_CONTROL_AF_STATE_INACTIVE,
+
+    ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN,
+
+    ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED,
+
+    ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN,
+
+    ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED,
+
+    ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED,
+
+    ANDROID_CONTROL_AF_STATE_PASSIVE_UNFOCUSED,
+
+};
+
+enum CameraMetadataEnumAndroidControlAwbState : uint32_t {
+    ANDROID_CONTROL_AWB_STATE_INACTIVE,
+
+    ANDROID_CONTROL_AWB_STATE_SEARCHING,
+
+    ANDROID_CONTROL_AWB_STATE_CONVERGED,
+
+    ANDROID_CONTROL_AWB_STATE_LOCKED,
+
+};
+
+enum CameraMetadataEnumAndroidControlAeLockAvailable : uint32_t {
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE,
+
+    ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE,
+
+};
+
+enum CameraMetadataEnumAndroidControlAwbLockAvailable : uint32_t {
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE,
+
+    ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE,
+
+};
+
+enum CameraMetadataEnumAndroidDemosaicMode : uint32_t {
+    ANDROID_DEMOSAIC_MODE_FAST,
+
+    ANDROID_DEMOSAIC_MODE_HIGH_QUALITY,
+
+};
+
+enum CameraMetadataEnumAndroidEdgeMode : uint32_t {
+    ANDROID_EDGE_MODE_OFF,
+
+    ANDROID_EDGE_MODE_FAST,
+
+    ANDROID_EDGE_MODE_HIGH_QUALITY,
+
+    ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG,
+
+};
+
+enum CameraMetadataEnumAndroidFlashMode : uint32_t {
+    ANDROID_FLASH_MODE_OFF,
+
+    ANDROID_FLASH_MODE_SINGLE,
+
+    ANDROID_FLASH_MODE_TORCH,
+
+};
+
+enum CameraMetadataEnumAndroidFlashState : uint32_t {
+    ANDROID_FLASH_STATE_UNAVAILABLE,
+
+    ANDROID_FLASH_STATE_CHARGING,
+
+    ANDROID_FLASH_STATE_READY,
+
+    ANDROID_FLASH_STATE_FIRED,
+
+    ANDROID_FLASH_STATE_PARTIAL,
+
+};
+
+enum CameraMetadataEnumAndroidFlashInfoAvailable : uint32_t {
+    ANDROID_FLASH_INFO_AVAILABLE_FALSE,
+
+    ANDROID_FLASH_INFO_AVAILABLE_TRUE,
+
+};
+
+enum CameraMetadataEnumAndroidHotPixelMode : uint32_t {
+    ANDROID_HOT_PIXEL_MODE_OFF,
+
+    ANDROID_HOT_PIXEL_MODE_FAST,
+
+    ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY,
+
+};
+
+enum CameraMetadataEnumAndroidLensOpticalStabilizationMode : uint32_t {
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
+
+    ANDROID_LENS_OPTICAL_STABILIZATION_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidLensFacing : uint32_t {
+    ANDROID_LENS_FACING_FRONT,
+
+    ANDROID_LENS_FACING_BACK,
+
+    ANDROID_LENS_FACING_EXTERNAL,
+
+};
+
+enum CameraMetadataEnumAndroidLensState : uint32_t {
+    ANDROID_LENS_STATE_STATIONARY,
+
+    ANDROID_LENS_STATE_MOVING,
+
+};
+
+enum CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration : uint32_t {
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED,
+
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE,
+
+    ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED,
+
+};
+
+enum CameraMetadataEnumAndroidNoiseReductionMode : uint32_t {
+    ANDROID_NOISE_REDUCTION_MODE_OFF,
+
+    ANDROID_NOISE_REDUCTION_MODE_FAST,
+
+    ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY,
+
+    ANDROID_NOISE_REDUCTION_MODE_MINIMAL,
+
+    ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG,
+
+};
+
+enum CameraMetadataEnumAndroidQuirksPartialResult : uint32_t {
+    ANDROID_QUIRKS_PARTIAL_RESULT_FINAL,
+
+    ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL,
+
+};
+
+enum CameraMetadataEnumAndroidRequestMetadataMode : uint32_t {
+    ANDROID_REQUEST_METADATA_MODE_NONE,
+
+    ANDROID_REQUEST_METADATA_MODE_FULL,
+
+};
+
+enum CameraMetadataEnumAndroidRequestType : uint32_t {
+    ANDROID_REQUEST_TYPE_CAPTURE,
+
+    ANDROID_REQUEST_TYPE_REPROCESS,
+
+};
+
+enum CameraMetadataEnumAndroidRequestAvailableCapabilities : uint32_t {
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
+
+    ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
+
+};
+
+enum CameraMetadataEnumAndroidScalerAvailableFormats : uint32_t {
+    ANDROID_SCALER_AVAILABLE_FORMATS_RAW16 = 0x20,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_RAW_OPAQUE = 0x24,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_YV12 = 0x32315659,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_YCrCb_420_SP = 0x11,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED = 0x22,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888 = 0x23,
+
+    ANDROID_SCALER_AVAILABLE_FORMATS_BLOB = 0x21,
+
+};
+
+enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurations : uint32_t {
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
+
+    ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
+
+};
+
+enum CameraMetadataEnumAndroidScalerCroppingType : uint32_t {
+    ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY,
+
+    ANDROID_SCALER_CROPPING_TYPE_FREEFORM,
+
+};
+
+enum CameraMetadataEnumAndroidSensorReferenceIlluminant1 : uint32_t {
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D55 = 20,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D65 = 21,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D75 = 22,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D50 = 23,
+
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24,
+
+};
+
+enum CameraMetadataEnumAndroidSensorTestPatternMode : uint32_t {
+    ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE_PN9,
+
+    ANDROID_SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256,
+
+};
+
+enum CameraMetadataEnumAndroidSensorInfoColorFilterArrangement : uint32_t {
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
+
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
+
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
+
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR,
+
+    ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB,
+
+};
+
+enum CameraMetadataEnumAndroidSensorInfoTimestampSource : uint32_t {
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN,
+
+    ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME,
+
+};
+
+enum CameraMetadataEnumAndroidSensorInfoLensShadingApplied : uint32_t {
+    ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED_FALSE,
+
+    ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED_TRUE,
+
+};
+
+enum CameraMetadataEnumAndroidShadingMode : uint32_t {
+    ANDROID_SHADING_MODE_OFF,
+
+    ANDROID_SHADING_MODE_FAST,
+
+    ANDROID_SHADING_MODE_HIGH_QUALITY,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsFaceDetectMode : uint32_t {
+    ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
+
+    ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
+
+    ANDROID_STATISTICS_FACE_DETECT_MODE_FULL,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsHistogramMode : uint32_t {
+    ANDROID_STATISTICS_HISTOGRAM_MODE_OFF,
+
+    ANDROID_STATISTICS_HISTOGRAM_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsSharpnessMapMode : uint32_t {
+    ANDROID_STATISTICS_SHARPNESS_MAP_MODE_OFF,
+
+    ANDROID_STATISTICS_SHARPNESS_MAP_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsHotPixelMapMode : uint32_t {
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF,
+
+    ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsSceneFlicker : uint32_t {
+    ANDROID_STATISTICS_SCENE_FLICKER_NONE,
+
+    ANDROID_STATISTICS_SCENE_FLICKER_50HZ,
+
+    ANDROID_STATISTICS_SCENE_FLICKER_60HZ,
+
+};
+
+enum CameraMetadataEnumAndroidStatisticsLensShadingMapMode : uint32_t {
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF,
+
+    ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON,
+
+};
+
+enum CameraMetadataEnumAndroidTonemapMode : uint32_t {
+    ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
+
+    ANDROID_TONEMAP_MODE_FAST,
+
+    ANDROID_TONEMAP_MODE_HIGH_QUALITY,
+
+    ANDROID_TONEMAP_MODE_GAMMA_VALUE,
+
+    ANDROID_TONEMAP_MODE_PRESET_CURVE,
+
+};
+
+enum CameraMetadataEnumAndroidTonemapPresetCurve : uint32_t {
+    ANDROID_TONEMAP_PRESET_CURVE_SRGB,
+
+    ANDROID_TONEMAP_PRESET_CURVE_REC709,
+
+};
+
+enum CameraMetadataEnumAndroidLedTransmit : uint32_t {
+    ANDROID_LED_TRANSMIT_OFF,
+
+    ANDROID_LED_TRANSMIT_ON,
+
+};
+
+enum CameraMetadataEnumAndroidLedAvailableLeds : uint32_t {
+    ANDROID_LED_AVAILABLE_LEDS_TRANSMIT,
+
+};
+
+enum CameraMetadataEnumAndroidInfoSupportedHardwareLevel : uint32_t {
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
+
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
+
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
+
+    ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
+
+};
+
+enum CameraMetadataEnumAndroidBlackLevelLock : uint32_t {
+    ANDROID_BLACK_LEVEL_LOCK_OFF,
+
+    ANDROID_BLACK_LEVEL_LOCK_ON,
+
+};
+
+enum CameraMetadataEnumAndroidSyncFrameNumber : uint32_t {
+    ANDROID_SYNC_FRAME_NUMBER_CONVERGING = -1,
+
+    ANDROID_SYNC_FRAME_NUMBER_UNKNOWN = -2,
+
+};
+
+enum CameraMetadataEnumAndroidSyncMaxLatency : uint32_t {
+    ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL = 0,
+
+    ANDROID_SYNC_MAX_LATENCY_UNKNOWN = -1,
+
+};
+
+enum CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations : uint32_t {
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
+
+    ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_INPUT,
+
+};
+
+enum CameraMetadataEnumAndroidDepthDepthIsExclusive : uint32_t {
+    ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE,
+
+    ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_TRUE,
+
+};
diff --git a/camera/metadata/README.md b/camera/metadata/README.md
new file mode 100644
index 0000000..752973d
--- /dev/null
+++ b/camera/metadata/README.md
@@ -0,0 +1,19 @@
+## Camera Metadata Interface ##
+---
+
+## Overview: ##
+
+The camera.metadata interface is used by the Android camera service,
+camera provider and camera devices to retrieve static camera information and issue
+camera capture controls.
+
+See the docs.html for each version for the detailed description of each metadata
+specification.
+## Version history: ##
+
+### @3.2:
+
+HIDL version of the baseline camera metadata interface, required by
+camera.provider@2.4 and camera.device@3.2 onwards.
+
+
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
new file mode 100644
index 0000000..f5f10de
--- /dev/null
+++ b/camera/provider/2.4/Android.bp
@@ -0,0 +1,66 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.camera.provider@2.4_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.provider@2.4",
+    srcs: [
+        "ICameraProvider.hal",
+        "ICameraProviderCallback.hal",
+    ],
+    out: [
+        "android/hardware/camera/provider/2.4/CameraProviderAll.cpp",
+        "android/hardware/camera/provider/2.4/CameraProviderCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.provider@2.4_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.provider@2.4",
+    srcs: [
+        "ICameraProvider.hal",
+        "ICameraProviderCallback.hal",
+    ],
+    out: [
+        "android/hardware/camera/provider/2.4/ICameraProvider.h",
+        "android/hardware/camera/provider/2.4/IHwCameraProvider.h",
+        "android/hardware/camera/provider/2.4/BnHwCameraProvider.h",
+        "android/hardware/camera/provider/2.4/BpHwCameraProvider.h",
+        "android/hardware/camera/provider/2.4/BsCameraProvider.h",
+        "android/hardware/camera/provider/2.4/ICameraProviderCallback.h",
+        "android/hardware/camera/provider/2.4/IHwCameraProviderCallback.h",
+        "android/hardware/camera/provider/2.4/BnHwCameraProviderCallback.h",
+        "android/hardware/camera/provider/2.4/BpHwCameraProviderCallback.h",
+        "android/hardware/camera/provider/2.4/BsCameraProviderCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.camera.provider@2.4",
+    generated_sources: ["android.hardware.camera.provider@2.4_genc++"],
+    generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/camera/provider/2.4/ICameraProvider.hal b/camera/provider/2.4/ICameraProvider.hal
new file mode 100644
index 0000000..3015b7d
--- /dev/null
+++ b/camera/provider/2.4/ICameraProvider.hal
@@ -0,0 +1,188 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.provider@2.4;
+
+import ICameraProviderCallback;
+import android.hardware.camera.common@1.0::types;
+import android.hardware.camera.device@1.0::ICameraDevice;
+import android.hardware.camera.device@3.2::ICameraDevice;
+
+/**
+ * Camera provider HAL, which enumerates the available individual camera devices
+ * known to the provider, and provides updates about changes to device status,
+ * such as connection, disconnection, or torch mode enable/disable.
+ *
+ * The provider is responsible for generating a list of camera device service
+ * names that can then be opened via the hardware service manager.
+ *
+ * Multiple camera provider HALs may be present in a single system.
+ * For discovery, the service names, and process names, must be of the form
+ * "android.hardware.camera.provider@<major>.<minor>/<type>/<instance>"
+ * where
+ *   - <major>/<minor> is the provider HAL HIDL version,
+ *   - <type> is the type of devices this provider knows about, such as
+ *     "internal", "legacy", "usb", or "remote"
+ *   - <instance> is a non-negative integer starting from 0 to disambiguate
+ *     between multiple HALs of the same type.
+ *
+ * The "legacy" type is only used for passthrough legacy HAL mode, and must
+ * not be used by a standalone binderized HAL.
+ *
+ * The device instance names enumerated by the provider must be of the form
+ * "device@<major>.<minor>/<type>/<id>" where
+ * <major>/<minor> is the HIDL version of the interface. <id> is either a small
+ * incrementing integer for "internal" device types, with 0 being the main
+ * back-facing camera and 1 being the main front-facing camera, if they exist.
+ * Or, for external devices such as type "usb", a unique serial number that can
+ * be used to identify the device reliably when it is disconnected and
+ * reconnected. Multiple providers may not enumerate the same device ID.
+ *
+ */
+interface ICameraProvider {
+
+    /**
+     * setCallback:
+     *
+     * Provide a callback interface to the HAL provider to inform framework of
+     * asynchronous camera events. The framework must call this function once
+     * during camera service startup, before any other calls to the provider
+     * (note that in case the camera service restarts, this method must be
+     * invoked again during its startup).
+     *
+     * @param callback
+     *     A non-null callback interface to invoke when camera events occur.
+     * @return status
+     *     Status code for the operation, one of:
+     *     OK:
+     *         On success
+     *     INTERNAL_ERROR:
+     *         An unexpected internal error occurred while setting the callbacks
+     *     ILLEGAL_ARGUMENT:
+     *         The callback argument is invalid (for example, null).
+     *
+     */
+    setCallback(ICameraProviderCallback callback) generates (Status status);
+
+    /**
+     * getVendorTags:
+     *
+     * Retrieve all vendor tags supported by devices discoverable through this
+     * provider. The tags are grouped into sections.
+     *
+     * @return status
+     *     Status code for the operation, one of:
+     *     OK:
+     *         On success
+     *     INTERNAL_ERROR:
+     *         An unexpected internal error occurred while setting the callbacks
+     * @return sections
+     *     The supported vendor tag sections; empty if there are no supported
+     *     vendor tags, or status is not OK.
+     *
+     */
+    getVendorTags() generates (Status status, vec<VendorTagSection> sections);
+
+    /**
+     * getCameraDeviceList:
+     *
+     * Returns the list of internal camera device interfaces known to this
+     * camera provider. These devices can then be accessed via the hardware
+     * service manager.
+     *
+     * External camera devices (camera facing EXTERNAL) must be reported through
+     * the device status change callback, not in this list. Only devices with
+     * facing BACK or FRONT must be listed here.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a succesful generation of camera ID list
+     *     INTERNAL_ERROR:
+     *         A camera ID list cannot be created. This may be due to
+     *         a failure to initialize the camera subsystem, for example.
+     * @return cameraDeviceServiceNames The vector of internal camera device
+     *     names known to this provider.
+     */
+    getCameraIdList()
+            generates (Status status, vec<string> cameraDeviceNames);
+
+    /**
+     * isSetTorchModeSupported:
+     *
+     * Returns if the camera devices known to this camera provider support
+     * setTorchMode API or not. If the provider does not support setTorchMode
+     * API, calling to setTorchMode will return METHOD_NOT_SUPPORTED.
+     *
+     * Note that not every camera device has a flash unit, so even this API
+     * returns true, setTorchMode call might still fail due to the camera device
+     * does not have a flash unit. In such case, the returned status will be
+     * OPERATION_NOT_SUPPORTED.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a succesful call
+     *     INTERNAL_ERROR:
+     *         Torch API support cannot be queried. This may be due to
+     *         a failure to initialize the camera subsystem, for example.
+     * @return support Whether the camera devices known to this provider
+     *     supports setTorchMode API or not.
+     *
+     */
+    isSetTorchModeSupported() generates (Status status, bool support);
+
+    /**
+     * getCameraDeviceInterface_VN_x:
+     *
+     * Return a android.hardware.camera.device@N.x/ICameraDevice interface for
+     * the requested device name. This does not power on the camera device, but
+     * simply acquires the interface for querying the device static information,
+     * or to additionally open the device for active use.
+     *
+     * A separate method is required for each major revision of the camera device
+     * HAL interface, since they are not compatible with each other.
+     *
+     * Valid device names for this provider can be obtained via either
+     * getCameraIdList(), or via availability callbacks from
+     * ICameraProviderCallback::cameraDeviceStatusChange().
+     *
+     * The returned interface must be of the highest defined minor version for
+     * the major version; it's the responsibility of the HAL client to ensure
+     * they do not use methods/etc that are not valid for the actual minor
+     * version of the device.
+     *
+     * @param cameraDeviceName the name of the device to get an interface to.
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a succesful generation of camera ID list
+     *     ILLEGAL_ARGUMENT:
+     *         This device name is unknown, or has been disconnected
+     *     OPERATION_NOT_SUPPORTED:
+     *         The specified device does not support this major version of the
+     *         HAL interface.
+     *     INTERNAL_ERROR:
+     *         A camera interface cannot be returned due to an unexpected
+     *         internal error.
+     * @return device The inteface to this camera device, or null in case of
+     *     error.
+     */
+    getCameraDeviceInterface_V1_x(string cameraDeviceName) generates
+            (Status status,
+             android.hardware.camera.device@1.0::ICameraDevice device);
+    getCameraDeviceInterface_V3_x(string cameraDeviceName) generates
+            (Status status,
+             android.hardware.camera.device@3.2::ICameraDevice device);
+
+};
diff --git a/camera/provider/2.4/ICameraProviderCallback.hal b/camera/provider/2.4/ICameraProviderCallback.hal
new file mode 100644
index 0000000..63dd3c5
--- /dev/null
+++ b/camera/provider/2.4/ICameraProviderCallback.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.provider@2.4;
+
+import android.hardware.camera.common@1.0::types;
+
+/**
+ * Callback functions for a camera provider HAL to use to inform the camera
+ * service of changes to the camera subsystem.
+ */
+interface ICameraProviderCallback {
+
+    /**
+     * cameraDeviceStatusChange:
+     *
+     * Callback to the camera service to indicate that the state of a specific
+     * camera device has changed.
+     *
+     * On camera service startup, when ICameraProvider::setCallback is invoked,
+     * the camera service must assume that all internal camera devices are in
+     * the CAMERA_DEVICE_STATUS_PRESENT state.
+     *
+     * The provider must call this method to inform the camera service of any
+     * initially NOT_PRESENT devices, and of any external camera devices that
+     * are already present, as soon as the callbacks are available through
+     * setCallback.
+     *
+     * @param cameraDeviceServiceName The name of the camera device that has a
+     *     new status.
+     * @param newStatus The new status that device is in.
+     *
+     */
+    cameraDeviceStatusChange(string cameraDeviceName,
+            CameraDeviceStatus newStatus);
+
+    /**
+     * torchModeStatusChange:
+     *
+     * Callback to the camera service to indicate that the state of the torch
+     * mode of the flash unit associated with a specific camera device has
+     * changed. At provider registration time, the camera service must assume
+     * the torch modes are in the TORCH_MODE_STATUS_AVAILABLE_OFF state if
+     * android.flash.info.available is reported as true via the
+     * ICameraDevice::getCameraCharacteristics call.
+     *
+     * @param cameraDeviceServiceName The name of the camera device that has a
+     *     new status.
+     * @param newStatus The new status that device is in.
+     *
+     */
+    torchModeStatusChange(string cameraDeviceName,
+            TorchModeStatus newStatus);
+
+};
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
new file mode 100644
index 0000000..ee40ce5
--- /dev/null
+++ b/camera/provider/2.4/default/Android.bp
@@ -0,0 +1,49 @@
+cc_library_shared {
+    name: "android.hardware.camera.provider@2.4-impl",
+    relative_install_path: "hw",
+    srcs: ["CameraProvider.cpp"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.2-impl",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.common@1.0",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata"
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ]
+}
+
+cc_binary {
+    name: "android.hardware.camera.provider@2.4-service",
+    relative_install_path: "hw",
+    srcs: ["service.cpp", "CameraProvider.cpp"],
+    compile_multilib: "32",
+    init_rc: ["android.hardware.camera.provider@2.4-service.rc"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libhwbinder",
+        "libutils",
+        "libhardware",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.common@1.0",
+        "libcutils",
+        "android.hardware.camera.device@3.2-impl-binderized",
+        "libcamera_metadata"
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper"
+    ]
+}
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
new file mode 100644
index 0000000..1a34aa6
--- /dev/null
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CamProvider@2.4-impl"
+#include <android/log.h>
+
+#include "CameraProvider.h"
+#include "CameraDevice.h"
+#include <string.h>
+#include <utils/Trace.h>
+
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_4 {
+namespace implementation {
+
+namespace {
+const char *kLegacyProviderName = "legacy/0";
+// "device@<version>/legacy/<id>"
+const std::regex kDeviceNameRE("device@([0-9]+\\.[0-9]+)/legacy/(.+)");
+const char *kHAL3_2 = "3.2";
+const char *kHAL1_0 = "1.0";
+const int kMaxCameraDeviceNameLen = 128;
+const int kMaxCameraIdLen = 16;
+
+} // anonymous namespace
+
+using ::android::hardware::camera::common::V1_0::CameraMetadataType;
+using ::android::hardware::camera::common::V1_0::Status;
+
+/**
+ * static callback forwarding methods from HAL to instance
+ */
+void CameraProvider::sCameraDeviceStatusChange(
+        const struct camera_module_callbacks* callbacks,
+        int camera_id,
+        int new_status) {
+    ALOGI("%s++", __FUNCTION__);
+    sp<CameraProvider> cp = const_cast<CameraProvider*>(
+            static_cast<const CameraProvider*>(callbacks));
+
+    if (cp == nullptr) {
+        ALOGE("%s: callback ops is null", __FUNCTION__);
+        return;
+    }
+
+    ALOGI("%s resolved provider %p", __FUNCTION__, cp.get());
+
+    Mutex::Autolock _l(cp->mCbLock);
+    char cameraId[kMaxCameraIdLen];
+    snprintf(cameraId, sizeof(cameraId), "%d", camera_id);
+    std::string cameraIdStr(cameraId);
+    cp->mCameraStatusMap[cameraIdStr] = (camera_device_status_t) new_status;
+    if (cp->mCallbacks != nullptr) {
+        CameraDeviceStatus status = (CameraDeviceStatus) new_status;
+        for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
+            if (cameraIdStr.compare(deviceNamePair.first) == 0) {
+                cp->mCallbacks->cameraDeviceStatusChange(
+                        deviceNamePair.second, status);
+            }
+        }
+    }
+    ALOGI("%s--", __FUNCTION__);
+}
+
+void CameraProvider::sTorchModeStatusChange(
+        const struct camera_module_callbacks* callbacks,
+        const char* camera_id,
+        int new_status) {
+    ALOGI("%s++", __FUNCTION__);
+    sp<CameraProvider> cp = const_cast<CameraProvider*>(
+            static_cast<const CameraProvider*>(callbacks));
+
+    if (cp == nullptr) {
+        ALOGE("%s: callback ops is null", __FUNCTION__);
+        return;
+    }
+
+    ALOGI("%s resolved provider %p", __FUNCTION__, cp.get());
+
+    Mutex::Autolock _l(cp->mCbLock);
+    if (cp->mCallbacks != nullptr) {
+        std::string cameraIdStr(camera_id);
+        TorchModeStatus status = (TorchModeStatus) new_status;
+        for (auto const& deviceNamePair : cp->mCameraDeviceNames) {
+            if (cameraIdStr.compare(deviceNamePair.first) == 0) {
+                cp->mCallbacks->torchModeStatusChange(
+                        deviceNamePair.second, status);
+            }
+        }
+    }
+    ALOGI("%s--", __FUNCTION__);
+}
+
+Status CameraProvider::getHidlStatus(int status) {
+    switch (status) {
+        case 0: return Status::OK;
+        case -ENODEV: return Status::INTERNAL_ERROR;
+        case -EINVAL: return Status::ILLEGAL_ARGUMENT;
+        default:
+            ALOGE("%s: unknown HAL status code %d", __FUNCTION__, status);
+            return Status::INTERNAL_ERROR;
+    }
+}
+
+bool CameraProvider::matchDeviceName(const hidl_string& deviceName, std::smatch& sm) {
+    std::string deviceNameStd(deviceName.c_str());
+    return std::regex_match(deviceNameStd, sm, kDeviceNameRE);
+}
+
+std::string CameraProvider::getLegacyCameraId(const hidl_string& deviceName) {
+    std::smatch sm;
+    bool match = matchDeviceName(deviceName, sm);
+    if (!match) {
+        return std::string("");
+    }
+    return sm[2];
+}
+
+int CameraProvider::getCameraDeviceVersion(const hidl_string& deviceName) {
+    std::smatch sm;
+    bool match = matchDeviceName(deviceName, sm);
+    if (!match) {
+        return -1;
+    }
+    if (sm[1].compare(kHAL3_2) == 0) {
+        // maybe switched to 3.4 or define the hidl version enum later
+        return CAMERA_DEVICE_API_VERSION_3_2;
+    } else if (sm[1].compare(kHAL1_0) == 0) {
+        return CAMERA_DEVICE_API_VERSION_1_0;
+    }
+    return 0;
+}
+
+std::string CameraProvider::getHidlDeviceName(
+        std::string cameraId, int deviceVersion) {
+    // Maybe consider create a version check method and SortedVec to speed up?
+    if (deviceVersion != CAMERA_DEVICE_API_VERSION_1_0 &&
+            deviceVersion != CAMERA_DEVICE_API_VERSION_3_2 &&
+            deviceVersion != CAMERA_DEVICE_API_VERSION_3_3 &&
+            deviceVersion != CAMERA_DEVICE_API_VERSION_3_4 ) {
+        return hidl_string("");
+    }
+    const char* versionStr = (deviceVersion == CAMERA_DEVICE_API_VERSION_1_0) ? kHAL1_0 : kHAL3_2;
+    char deviceName[kMaxCameraDeviceNameLen];
+    snprintf(deviceName, sizeof(deviceName), "device@%s/legacy/%s",
+            versionStr, cameraId.c_str());
+    return deviceName;
+}
+
+CameraProvider::CameraProvider() :
+        camera_module_callbacks_t({sCameraDeviceStatusChange,
+                                   sTorchModeStatusChange}) {
+    mInitFailed = initialize();
+}
+
+CameraProvider::~CameraProvider() {}
+
+bool CameraProvider::initialize() {
+    camera_module_t *rawModule;
+    int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID,
+            (const hw_module_t **)&rawModule);
+    if (err < 0) {
+        ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err));
+        return true;
+    }
+
+    mModule = new CameraModule(rawModule);
+    err = mModule->init();
+    if (err != OK) {
+        ALOGE("Could not initialize camera HAL module: %d (%s)", err,
+            strerror(-err));
+        mModule.clear();
+        return true;
+    }
+    ALOGI("Loaded \"%s\" camera module", mModule->getModuleName());
+
+    mNumberOfLegacyCameras = mModule->getNumberOfCameras();
+    for (int i = 0; i < mNumberOfLegacyCameras; i++) {
+        char cameraId[kMaxCameraIdLen];
+        snprintf(cameraId, sizeof(cameraId), "%d", i);
+        std::string cameraIdStr(cameraId);
+        mCameraStatusMap[cameraIdStr] = CAMERA_DEVICE_STATUS_PRESENT;
+        mCameraIds.add(cameraIdStr);
+
+        // initialize mCameraDeviceNames and mOpenLegacySupported
+        mOpenLegacySupported[cameraIdStr] = false;
+        int deviceVersion = mModule->getDeviceVersion(i);
+        mCameraDeviceNames.add(
+                std::make_pair(cameraIdStr,
+                               getHidlDeviceName(cameraIdStr, deviceVersion)));
+        if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_2 &&
+                mModule->isOpenLegacyDefined()) {
+            // try open_legacy to see if it actually works
+            struct hw_device_t* halDev = nullptr;
+            int ret = mModule->openLegacy(cameraId, CAMERA_DEVICE_API_VERSION_1_0, &halDev);
+            if (ret == 0) {
+                mOpenLegacySupported[cameraIdStr] = true;
+                halDev->close(halDev);
+                mCameraDeviceNames.add(
+                        std::make_pair(cameraIdStr,
+                                getHidlDeviceName(cameraIdStr, CAMERA_DEVICE_API_VERSION_1_0)));
+            } else if (ret == -EBUSY || ret == -EUSERS) {
+                // Looks like this provider instance is not initialized during
+                // system startup and there are other camera users already.
+                // Not a good sign but not fatal.
+                ALOGW("%s: open_legacy try failed!", __FUNCTION__);
+            }
+        }
+    }
+
+    // Setup vendor tags here so HAL can setup vendor keys in camera characteristics
+    VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+    bool setupSucceed = setUpVendorTags();
+    return !setupSucceed; // return flag here is mInitFailed
+}
+
+bool CameraProvider::setUpVendorTags() {
+    ATRACE_CALL();
+    vendor_tag_ops_t vOps = vendor_tag_ops_t();
+
+    // Check if vendor operations have been implemented
+    if (!mModule->isVendorTagDefined()) {
+        ALOGI("%s: No vendor tags defined for this device.", __FUNCTION__);
+        return false;
+    }
+
+    mModule->getVendorTagOps(&vOps);
+
+    // Ensure all vendor operations are present
+    if (vOps.get_tag_count == nullptr || vOps.get_all_tags == nullptr ||
+            vOps.get_section_name == nullptr || vOps.get_tag_name == nullptr ||
+            vOps.get_tag_type == nullptr) {
+        ALOGE("%s: Vendor tag operations not fully defined. Ignoring definitions."
+               , __FUNCTION__);
+        return false;
+    }
+
+    // Read all vendor tag definitions into a descriptor
+    sp<VendorTagDescriptor> desc;
+    status_t res;
+    if ((res = VendorTagDescriptor::createDescriptorFromOps(&vOps, /*out*/desc))
+            != OK) {
+        ALOGE("%s: Could not generate descriptor from vendor tag operations,"
+              "received error %s (%d). Camera clients will not be able to use"
+              "vendor tags", __FUNCTION__, strerror(res), res);
+        return false;
+    }
+
+    // Set the global descriptor to use with camera metadata
+    VendorTagDescriptor::setAsGlobalVendorTagDescriptor(desc);
+    const SortedVector<String8>* sectionNames = desc->getAllSectionNames();
+    size_t numSections = sectionNames->size();
+    std::vector<std::vector<VendorTag>> tagsBySection(numSections);
+    int tagCount = desc->getTagCount();
+    std::vector<uint32_t> tags(tagCount);
+    desc->getTagArray(tags.data());
+    for (int i = 0; i < tagCount; i++) {
+        VendorTag vt;
+        vt.tagId = tags[i];
+        vt.tagName = desc->getTagName(tags[i]);
+        vt.tagType = (CameraMetadataType) desc->getTagType(tags[i]);
+        ssize_t sectionIdx = desc->getSectionIndex(tags[i]);
+        tagsBySection[sectionIdx].push_back(vt);
+    }
+    mVendorTagSections.resize(numSections);
+    for (size_t s = 0; s < numSections; s++) {
+        mVendorTagSections[s].sectionName = (*sectionNames)[s].string();
+        mVendorTagSections[s].tags = tagsBySection[s];
+    }
+    return true;
+}
+
+// Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+Return<Status> CameraProvider::setCallback(const sp<ICameraProviderCallback>& callback)  {
+    {
+        Mutex::Autolock _l(mCbLock);
+        mCallbacks = callback;
+    } // release lock here because HAL might send callbacks in setCallbacks call
+    return getHidlStatus(mModule->setCallbacks(this));
+}
+
+Return<void> CameraProvider::getVendorTags(getVendorTags_cb _hidl_cb)  {
+    _hidl_cb(Status::OK, mVendorTagSections);
+    return Void();
+}
+
+Return<void> CameraProvider::getCameraIdList(getCameraIdList_cb _hidl_cb)  {
+    std::vector<hidl_string> deviceNameList;
+    for (auto const& deviceNamePair : mCameraDeviceNames) {
+        if (mCameraStatusMap[deviceNamePair.first] == CAMERA_DEVICE_STATUS_PRESENT) {
+            deviceNameList.push_back(deviceNamePair.second);
+        }
+    }
+    hidl_vec<hidl_string> hidlDeviceNameList(deviceNameList);
+    _hidl_cb(Status::OK, hidlDeviceNameList);
+    return Void();
+}
+
+Return<void> CameraProvider::isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) {
+    bool support = mModule->isSetTorchModeSupported();
+    _hidl_cb (Status::OK, support);
+    return Void();
+}
+
+Return<void> CameraProvider::getCameraDeviceInterface_V1_x(
+        const hidl_string& /*cameraDeviceName*/, getCameraDeviceInterface_V1_x_cb /*_hidl_cb*/)  {
+    // TODO implement after device 1.0 is implemented
+    return Void();
+}
+
+Return<void> CameraProvider::getCameraDeviceInterface_V3_x(
+        const hidl_string& cameraDeviceName, getCameraDeviceInterface_V3_x_cb _hidl_cb)  {
+    std::smatch sm;
+    bool match = matchDeviceName(cameraDeviceName, sm);
+    if (!match) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    std::string cameraId = sm[2];
+    std::string deviceVersion = sm[1];
+    std::string deviceName(cameraDeviceName.c_str());
+    ssize_t index = mCameraDeviceNames.indexOf(std::make_pair(cameraId, deviceName));
+    if (index == NAME_NOT_FOUND) { // Either an illegal name or a device version mismatch
+        Status status = Status::OK;
+        ssize_t idx = mCameraIds.indexOf(cameraId);
+        if (idx == NAME_NOT_FOUND) {
+            ALOGE("%s: cannot find camera %s!", __FUNCTION__, cameraId.c_str());
+            status = Status::ILLEGAL_ARGUMENT;
+        } else { // invalid version
+            ALOGE("%s: camera device %s does not support version %s!",
+                    __FUNCTION__, cameraId.c_str(), deviceVersion.c_str());
+            status = Status::OPERATION_NOT_SUPPORTED;
+        }
+        _hidl_cb(status, nullptr);
+        return Void();
+    }
+
+    if (mCameraStatusMap.count(cameraId) == 0 ||
+            mCameraStatusMap[cameraId] != CAMERA_DEVICE_STATUS_PRESENT) {
+        _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    // TODO: we also need to keep a wp list of all generated devices to notify
+    //       devices of device present status change, but then each device might
+    //       need a sp<provider> to keep provider alive until all device closed?
+    //       Problem: do we have external camera products to test this?
+    sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> device =
+            new android::hardware::camera::device::V3_2::implementation::CameraDevice(
+                    mModule, cameraId, mCameraDeviceNames);
+
+    if (device == nullptr) {
+        ALOGE("%s: cannot allocate camera device for id %s", __FUNCTION__, cameraId.c_str());
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    if (device->isInitFailed()) {
+        ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
+        device = nullptr;
+        _hidl_cb(Status::INTERNAL_ERROR, nullptr);
+        return Void();
+    }
+
+    _hidl_cb (Status::OK, device);
+    return Void();
+}
+
+ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name) {
+    if (strcmp(name, kLegacyProviderName) != 0) {
+        return nullptr;
+    }
+    CameraProvider* provider = new CameraProvider();
+    if (provider == nullptr) {
+        ALOGE("%s: cannot allocate camera provider!", __FUNCTION__);
+        return nullptr;
+    }
+    if (provider->isInitFailed()) {
+        ALOGE("%s: camera provider init failed!", __FUNCTION__);
+        delete provider;
+        return nullptr;
+    }
+    return provider;
+}
+
+} // namespace implementation
+}  // namespace V2_4
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/provider/2.4/default/CameraProvider.h b/camera/provider/2.4/default/CameraProvider.h
new file mode 100644
index 0000000..2a43e2f
--- /dev/null
+++ b/camera/provider/2.4/default/CameraProvider.h
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H
+#define ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H
+
+#include <regex>
+#include "hardware/camera_common.h"
+#include "utils/Mutex.h"
+#include "utils/SortedVector.h"
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include "CameraModule.h"
+#include "VendorTagDescriptor.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace provider {
+namespace V2_4 {
+namespace implementation {
+
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::TorchModeStatus;
+using ::android::hardware::camera::common::V1_0::VendorTag;
+using ::android::hardware::camera::common::V1_0::VendorTagSection;
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::camera::common::V1_0::helper::VendorTagDescriptor;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+struct CameraProvider : public ICameraProvider, public camera_module_callbacks_t {
+    CameraProvider();
+    ~CameraProvider();
+
+    // Caller must use this method to check if CameraProvider ctor failed
+    bool isInitFailed() { return mInitFailed; }
+
+    // Methods from ::android::hardware::camera::provider::V2_4::ICameraProvider follow.
+    Return<Status> setCallback(const sp<ICameraProviderCallback>& callback) override;
+    Return<void> getVendorTags(getVendorTags_cb _hidl_cb) override;
+    Return<void> getCameraIdList(getCameraIdList_cb _hidl_cb) override;
+    Return<void> isSetTorchModeSupported(isSetTorchModeSupported_cb _hidl_cb) override;
+    Return<void> getCameraDeviceInterface_V1_x(
+            const hidl_string& cameraDeviceName,
+            getCameraDeviceInterface_V1_x_cb _hidl_cb) override;
+    Return<void> getCameraDeviceInterface_V3_x(
+            const hidl_string& cameraDeviceName,
+            getCameraDeviceInterface_V3_x_cb _hidl_cb) override;
+
+private:
+    Mutex mCbLock;
+    sp<ICameraProviderCallback> mCallbacks = nullptr;
+
+    sp<CameraModule> mModule;
+
+    int mNumberOfLegacyCameras;
+    std::map<std::string, camera_device_status_t> mCameraStatusMap; // camera id -> status
+    std::map<std::string, bool> mOpenLegacySupported; // camera id -> open_legacy HAL1.0 supported
+    SortedVector<std::string> mCameraIds; // the "0"/"1" legacy camera Ids
+    // (cameraId string, hidl device name) pairs
+    SortedVector<std::pair<std::string, std::string>> mCameraDeviceNames;
+
+    // Must be queried before using any APIs.
+    // APIs will only work when this returns true
+    bool mInitFailed;
+    bool initialize();
+
+    hidl_vec<VendorTagSection> mVendorTagSections;
+    bool setUpVendorTags();
+
+    // extract legacy camera ID/device version from a HIDL device name
+    static bool matchDeviceName(const hidl_string& deviceName, std::smatch& sm);
+    static std::string getLegacyCameraId(const hidl_string& deviceName);
+    static int getCameraDeviceVersion(const hidl_string& deviceName);
+
+    // create HIDL device name from camera ID and device version
+    static std::string getHidlDeviceName(std::string cameraId, int deviceVersion);
+
+    // convert conventional HAL status to HIDL Status
+    static Status getHidlStatus(int);
+
+    // static callback forwarding methods
+    static void sCameraDeviceStatusChange(
+        const struct camera_module_callbacks* callbacks,
+        int camera_id,
+        int new_status);
+    static void sTorchModeStatusChange(
+        const struct camera_module_callbacks* callbacks,
+        const char* camera_id,
+        int new_status);
+};
+
+extern "C" ICameraProvider* HIDL_FETCH_ICameraProvider(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_4
+}  // namespace provider
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_PROVIDER_V2_4_CAMERAPROVIDER_H
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
new file mode 100644
index 0000000..31f0810
--- /dev/null
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
@@ -0,0 +1,6 @@
+service camera-provider-2-4 /system/bin/hw/android.hardware.camera.provider@2.4-service
+    class hal
+    user cameraserver
+    group audio camera input drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/camera-daemon/tasks /dev/stune/top-app/tasks
\ No newline at end of file
diff --git a/camera/provider/2.4/default/service.cpp b/camera/provider/2.4/default/service.cpp
new file mode 100644
index 0000000..2723dee
--- /dev/null
+++ b/camera/provider/2.4/default/service.cpp
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.camera.provider@2.4-service"
+
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <CameraProvider.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <utils/StrongPointer.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::sp;
+using android::hardware::camera::provider::V2_4::ICameraProvider;
+using android::hardware::camera::provider::V2_4::implementation::HIDL_FETCH_ICameraProvider;
+
+int main()
+{
+    const char instance[] = "legacy/0";
+
+    ALOGI("Camera provider Service is starting.");
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+    // TODO (b/34510650): check the passthrough/binderized dev key
+    sp<ICameraProvider> service = HIDL_FETCH_ICameraProvider(instance);
+    if (service == nullptr) {
+        ALOGI("Camera provider getService returned NULL");
+        return -1;
+    }
+
+    LOG_FATAL_IF(service->isRemote(), "Camera provider service is REMOTE!");
+
+    service->registerAsService(instance);
+    joinRpcThreadpool();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
new file mode 100644
index 0000000..4947c17
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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_test {
+    name: "camera_hidl_hal_test",
+    gtest: true,
+    srcs: ["camera_hidl_hal_test.cpp"],
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libcutils",
+        "libutils",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.device@3.2",
+        "libcamera_metadata"
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp b/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp
new file mode 100644
index 0000000..0eb291c
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/camera_hidl_hal_test.cpp
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "camera_hidl_hal_test"
+#include <android/hardware/camera/provider/2.4/ICameraProvider.h>
+#include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/log.h>
+#include <gtest/gtest.h>
+#include <regex>
+#include "system/camera_metadata.h"
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::sp;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::CameraDeviceStatus;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::TorchModeStatus;
+using ::android::hardware::camera::provider::V2_4::ICameraProvider;
+using ::android::hardware::camera::provider::V2_4::ICameraProviderCallback;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_2::CaptureResult;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceCallback;
+using ::android::hardware::camera::device::V3_2::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_2::NotifyMsg;
+using ::android::hardware::camera::device::V3_2::RequestTemplate;
+
+#define CAMERA_PASSTHROUGH_SERVICE_NAME "legacy/0"
+
+namespace {
+    // "device@<version>/legacy/<id>"
+    const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/legacy/(.+)";
+    const int CAMERA_DEVICE_API_VERSION_3_2 = 0x302;
+    const int CAMERA_DEVICE_API_VERSION_1_0 = 0x100;
+    const char *kHAL3_2 = "3.2";
+    const char *kHAL1_0 = "1.0";
+
+    bool matchDeviceName(const hidl_string& deviceName, std::smatch& sm) {
+        std::regex e(kDeviceNameRE);
+        std::string deviceNameStd(deviceName.c_str());
+        return std::regex_match(deviceNameStd, sm, e);
+    }
+
+    int getCameraDeviceVersion(const hidl_string& deviceName) {
+        std::smatch sm;
+        bool match = matchDeviceName(deviceName, sm);
+        if (!match) {
+            return -1;
+        }
+        if (sm[1].compare(kHAL3_2) == 0) {
+            // maybe switched to 3.4 or define the hidl version enumlater
+            return CAMERA_DEVICE_API_VERSION_3_2;
+        } else if (sm[1].compare(kHAL1_0) == 0) {
+            return CAMERA_DEVICE_API_VERSION_1_0;
+        }
+        return 0;
+    }
+}
+
+// Test environment for camera
+class CameraHidlEnvironment : public ::testing::Environment {
+public:
+    // get the test environment singleton
+    static CameraHidlEnvironment* Instance() {
+        static CameraHidlEnvironment* instance = new CameraHidlEnvironment;
+        return instance;
+    }
+
+    virtual void SetUp() override;
+    virtual void TearDown() override;
+
+    sp<ICameraProvider> mProvider;
+
+private:
+    CameraHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(CameraHidlEnvironment);
+};
+
+void CameraHidlEnvironment::SetUp() {
+    // TODO: test the binderized mode
+    mProvider = ICameraProvider::getService(CAMERA_PASSTHROUGH_SERVICE_NAME, true);
+    // TODO: handle the device doesn't have any camera case
+    ALOGI_IF(mProvider, "provider is not nullptr, %p", mProvider.get());
+    ASSERT_NE(mProvider, nullptr);
+}
+
+void CameraHidlEnvironment::TearDown() {
+    ALOGI("TearDown CameraHidlEnvironment");
+}
+
+// The main test class for camera HIDL HAL.
+class CameraHidlTest : public ::testing::Test {
+public:
+    virtual void SetUp() override {}
+    virtual void TearDown() override {}
+
+    hidl_vec<hidl_string> getCameraDeviceNames();
+
+    struct EmptyDeviceCb : public ICameraDeviceCallback {
+        virtual Return<void> processCaptureResult(const CaptureResult& /*result*/) override {
+            ALOGI("processCaptureResult callback");
+            ADD_FAILURE(); // Empty callback should not reach here
+            return Void();
+        }
+
+        virtual Return<void> notify(const NotifyMsg& /*msg*/) override {
+            ALOGI("notify callback");
+            ADD_FAILURE(); // Empty callback should not reach here
+            return Void();
+        }
+    };
+};
+
+hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames() {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames;
+    env->mProvider->getCameraIdList(
+        [&](auto status, const auto& idList) {
+            ALOGI("getCameraIdList returns status:%d", (int)status);
+            for (size_t i = 0; i < idList.size(); i++) {
+                ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
+            }
+            ASSERT_EQ(Status::OK, status);
+            cameraDeviceNames = idList;
+        });
+    return cameraDeviceNames;
+}
+
+// Test if ICameraProvider::isTorchModeSupported returns Status::OK
+TEST_F(CameraHidlTest, isTorchModeSupported) {
+    CameraHidlEnvironment::Instance()->mProvider->isSetTorchModeSupported(
+        [&](auto status, bool support) {
+            ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
+                    (int)status, support);
+            ASSERT_EQ(Status::OK, status);
+        });
+}
+
+// TODO: consider removing this test if getCameraDeviceNames() has the same coverage
+TEST_F(CameraHidlTest, getCameraIdList) {
+    CameraHidlEnvironment::Instance()->mProvider->getCameraIdList(
+        [&](auto status, const auto& idList) {
+            ALOGI("getCameraIdList returns status:%d", (int)status);
+            for (size_t i = 0; i < idList.size(); i++) {
+                ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
+            }
+            ASSERT_EQ(Status::OK, status);
+            // This is true for internal camera provider.
+            // Not necessary hold for external cameras providers
+            ASSERT_GT(idList.size(), 0u);
+        });
+}
+
+// Test if ICameraProvider::getVendorTags returns Status::OK
+TEST_F(CameraHidlTest, getVendorTags) {
+    CameraHidlEnvironment::Instance()->mProvider->getVendorTags(
+        [&](auto status, const auto& vendorTagSecs) {
+            ALOGI("getVendorTags returns status:%d numSections %zu",
+                    (int)status, vendorTagSecs.size());
+            for (size_t i = 0; i < vendorTagSecs.size(); i++) {
+                ALOGI("Vendor tag section %zu name %s",
+                        i, vendorTagSecs[i].sectionName.c_str());
+                for (size_t j = 0; j < vendorTagSecs[i].tags.size(); j++) {
+                    const auto& tag = vendorTagSecs[i].tags[j];
+                    ALOGI("Vendor tag id %u name %s type %d",
+                            tag.tagId,
+                            tag.tagName.c_str(),
+                            (int) tag.tagType);
+                }
+            }
+            ASSERT_EQ(Status::OK, status);
+        });
+}
+
+// Test if ICameraProvider::setCallback returns Status::OK
+TEST_F(CameraHidlTest, setCallback) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    struct ProviderCb : public ICameraProviderCallback {
+        virtual Return<void> cameraDeviceStatusChange(
+                const hidl_string& cameraDeviceName,
+                CameraDeviceStatus newStatus) override {
+            ALOGI("camera device status callback name %s, status %d",
+                    cameraDeviceName.c_str(), (int) newStatus);
+            return Void();
+        }
+
+        virtual Return<void> torchModeStatusChange(
+                const hidl_string& cameraDeviceName,
+                TorchModeStatus newStatus) override {
+            ALOGI("Torch mode status callback name %s, status %d",
+                    cameraDeviceName.c_str(), (int) newStatus);
+            return Void();
+        }
+    };
+    sp<ProviderCb> cb = new ProviderCb;
+    auto status = env->mProvider->setCallback(cb);
+    ASSERT_EQ(Status::OK, status);
+    // TODO: right now no callbacks are fired because there is no external camera
+    //       or torch mode change. Need to test torch API in CameraDevice test later.
+}
+
+// Test if ICameraProvider::getCameraDeviceInterface_V3_x returns Status::OK and non-null device
+TEST_F(CameraHidlTest, getCameraDeviceInterface_V3_x) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            env->mProvider->getCameraDeviceInterface_V3_x(
+                name,
+                [&](auto status, const auto& device3_2) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device3_2, nullptr);
+                });
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, getResourceCost) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("getResourceCost: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            device3_2->getResourceCost(
+                [&](auto status, const auto& resourceCost) {
+                    ALOGI("getResourceCost returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ALOGI("    Resource cost is %d", resourceCost.resourceCost);
+                    ASSERT_LE(resourceCost.resourceCost, 100u);
+                    for (const auto& name : resourceCost.conflictingDevices) {
+                        ALOGI("    Conflicting device: %s", name.c_str());
+                    }
+                });
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, getCameraCharacteristics) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            device3_2->getCameraCharacteristics(
+                [&](auto status, const auto& chars) {
+                    ALOGI("getCameraCharacteristics returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    const camera_metadata_t* metadata = (camera_metadata_t*) chars.data();
+                    size_t expectedSize = chars.size();
+                    ASSERT_EQ(0, validate_camera_metadata_structure(metadata, &expectedSize));
+                    size_t entryCount = get_camera_metadata_entry_count(metadata);
+                    // TODO: we can do better than 0 here. Need to check how many required
+                    // characteristics keys we've defined.
+                    ASSERT_GT(entryCount, 0u);
+                    ALOGI("getCameraCharacteristics metadata entry count is %zu", entryCount);
+                });
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, setTorchMode) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+    bool torchControlSupported = false;
+
+    CameraHidlEnvironment::Instance()->mProvider->isSetTorchModeSupported(
+        [&](auto status, bool support) {
+            ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
+                    (int)status, support);
+            ASSERT_EQ(Status::OK, status);
+            torchControlSupported = support;
+        });
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("setTorchMode: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            Status status = device3_2->setTorchMode(TorchMode::ON);
+            ALOGI("setTorchMode return status %d", (int)status);
+            if (!torchControlSupported) {
+                ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, status);
+            } else {
+                ASSERT_TRUE(status == Status::OK || status == Status::OPERATION_NOT_SUPPORTED);
+                if (status == Status::OK) {
+                    status = device3_2->setTorchMode(TorchMode::OFF);
+                    ASSERT_EQ(Status::OK, status);
+                }
+            }
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, dumpState) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("dumpState: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = 1; // std out
+            hidl_handle handle = raw_handle;
+            device3_2->dumpState(handle);
+            native_handle_delete(raw_handle);
+        }
+    }
+}
+
+// Open, dumpStates, then close
+TEST_F(CameraHidlTest, openClose) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("openClose: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+            sp<ICameraDeviceSession> session;
+            device3_2->open(
+                cb,
+                [&](auto status, const auto& newSession) {
+                    ALOGI("device::open returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(newSession, nullptr);
+                    session = newSession;
+                });
+
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = 1; // std out
+            hidl_handle handle = raw_handle;
+            device3_2->dumpState(handle);
+            native_handle_delete(raw_handle);
+
+            session->close();
+            // TODO: test all session API calls return INTERNAL_ERROR after close
+            // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, constructDefaultRequestSettings) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("constructDefaultRequestSettings: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+            sp<ICameraDeviceSession> session;
+            device3_2->open(
+                cb,
+                [&](auto status, const auto& newSession) {
+                    ALOGI("device::open returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(newSession, nullptr);
+                    session = newSession;
+                });
+
+            for (uint32_t t = (uint32_t) RequestTemplate::PREVIEW;
+                    t <= (uint32_t) RequestTemplate::MANUAL; t++) {
+                RequestTemplate reqTemplate = (RequestTemplate) t;
+                session->constructDefaultRequestSettings(
+                    reqTemplate,
+                    [&](auto status, const auto& req) {
+                        ALOGI("constructDefaultRequestSettings returns status:%d", (int)status);
+                        if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
+                                reqTemplate == RequestTemplate::MANUAL) {
+                            // optional templates
+                            ASSERT_TRUE(status == Status::OK || status == Status::ILLEGAL_ARGUMENT);
+                        } else {
+                            ASSERT_EQ(Status::OK, status);
+                        }
+
+                        if (status == Status::OK) {
+                            const camera_metadata_t* metadata =
+                                (camera_metadata_t*) req.data();
+                            size_t expectedSize = req.size();
+                            ASSERT_EQ(0, validate_camera_metadata_structure(
+                                    metadata, &expectedSize));
+                            size_t entryCount = get_camera_metadata_entry_count(metadata);
+                            // TODO: we can do better than 0 here. Need to check how many required
+                            // request keys we've defined for each template
+                            ASSERT_GT(entryCount, 0u);
+                            ALOGI("template %u metadata entry count is %zu", t, entryCount);
+                        } else {
+                            ASSERT_EQ(0u, req.size());
+                        }
+                    });
+            }
+            session->close();
+        }
+    }
+}
+
+TEST_F(CameraHidlTest, configureStreams) {
+    CameraHidlEnvironment* env = CameraHidlEnvironment::Instance();
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames();
+
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("configureStreams: Testing camera device %s", name.c_str());
+            env->mProvider->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_2 = device;
+                });
+
+            sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+            sp<ICameraDeviceSession> session;
+            device3_2->open(
+                cb,
+                [&](auto status, const auto& newSession) {
+                    ALOGI("device::open returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(newSession, nullptr);
+                    session = newSession;
+                });
+
+
+            session->close();
+        }
+    }
+}
+
+int main(int argc, char **argv) {
+  ::testing::AddGlobalTestEnvironment(CameraHidlEnvironment::Instance());
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/camera/provider/README.md b/camera/provider/README.md
new file mode 100644
index 0000000..0718fb1
--- /dev/null
+++ b/camera/provider/README.md
@@ -0,0 +1,37 @@
+## Camera Provider HAL ##
+---
+
+## Overview: ##
+
+The camera.provider HAL is used by the Android camera service to discover,
+query, and open individual camera devices.
+
+It also allows for direct control of the flash unit of camera devices that have
+one, for turning on/off torch mode.
+
+More complete information about the Android camera HAL and subsystem can be found at
+[source.android.com](http://source.android.com/devices/camera/index.html).
+
+## Version history: ##
+
+## types.hal: ##
+
+### @0.0:
+
+Common enum and struct definitions for all camera HAL interfaces. Does not
+define any interfaces of its own.
+
+## ICameraProvider.hal: ##
+
+### @2.4:
+
+First HIDL version of the camera provider HAL, closely matching the feature set
+and operation of the pre-HIDL camera HAL module v2.4.
+
+## ICameraProviderCallback.hal: ##
+
+### @2.4:
+
+First HIDL version of the camara provider HAL callback interface, closely
+matching the feature set and operation of the pre-HIDL camera HAL module
+callbacks v2.4.
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
new file mode 100644
index 0000000..5798306
--- /dev/null
+++ b/contexthub/1.0/Android.bp
@@ -0,0 +1,64 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.contexthub@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.contexthub@1.0",
+    srcs: [
+        "types.hal",
+        "IContexthub.hal",
+        "IContexthubCallback.hal",
+    ],
+    out: [
+        "android/hardware/contexthub/1.0/types.cpp",
+        "android/hardware/contexthub/1.0/ContexthubAll.cpp",
+        "android/hardware/contexthub/1.0/ContexthubCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.contexthub@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.contexthub@1.0",
+    srcs: [
+        "types.hal",
+        "IContexthub.hal",
+        "IContexthubCallback.hal",
+    ],
+    out: [
+        "android/hardware/contexthub/1.0/types.h",
+        "android/hardware/contexthub/1.0/IContexthub.h",
+        "android/hardware/contexthub/1.0/IHwContexthub.h",
+        "android/hardware/contexthub/1.0/BnHwContexthub.h",
+        "android/hardware/contexthub/1.0/BpHwContexthub.h",
+        "android/hardware/contexthub/1.0/BsContexthub.h",
+        "android/hardware/contexthub/1.0/IContexthubCallback.h",
+        "android/hardware/contexthub/1.0/IHwContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BnHwContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BpHwContexthubCallback.h",
+        "android/hardware/contexthub/1.0/BsContexthubCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.contexthub@1.0",
+    generated_sources: ["android.hardware.contexthub@1.0_genc++"],
+    generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/contexthub/1.0/Android.mk b/contexthub/1.0/Android.mk
new file mode 100644
index 0000000..c73c5c4
--- /dev/null
+++ b/contexthub/1.0/Android.mk
@@ -0,0 +1,658 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.contexthub@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (AsyncEventType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/AsyncEventType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.AsyncEventType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHub)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/ContextHub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.ContextHub
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHubMsg)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/ContextHubMsg.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.ContextHubMsg
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HostEndPoint)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HostEndPoint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HostEndPoint
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubAppInfo)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubAppInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubAppInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryFlag)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubMemoryFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubMemoryFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubMemoryType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubMemoryType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemRange)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/MemRange.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.MemRange
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppBinary)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/NanoAppBinary.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.NanoAppBinary
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppFlags)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/NanoAppFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.NanoAppFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PhysicalSensor)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/PhysicalSensor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.PhysicalSensor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SensorType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/SensorType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.SensorType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TransactionResult)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/TransactionResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.TransactionResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthub.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/IContexthub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthub.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::IContexthub
+
+$(GEN): $(LOCAL_PATH)/IContexthub.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthubCallback.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/IContexthubCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::IContexthubCallback
+
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.contexthub@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (AsyncEventType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/AsyncEventType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.AsyncEventType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHub)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/ContextHub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.ContextHub
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ContextHubMsg)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/ContextHubMsg.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.ContextHubMsg
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HostEndPoint)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HostEndPoint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HostEndPoint
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubAppInfo)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubAppInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubAppInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryFlag)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubMemoryFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubMemoryFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HubMemoryType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/HubMemoryType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.HubMemoryType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemRange)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/MemRange.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.MemRange
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppBinary)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/NanoAppBinary.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.NanoAppBinary
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanoAppFlags)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/NanoAppFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.NanoAppFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PhysicalSensor)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/PhysicalSensor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.PhysicalSensor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SensorType)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/SensorType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.SensorType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TransactionResult)
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/TransactionResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::types.TransactionResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthub.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/IContexthub.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthub.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::IContexthub
+
+$(GEN): $(LOCAL_PATH)/IContexthub.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IContexthubCallback.hal
+#
+GEN := $(intermediates)/android/hardware/contexthub/V1_0/IContexthubCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IContexthubCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.contexthub@1.0::IContexthubCallback
+
+$(GEN): $(LOCAL_PATH)/IContexthubCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/contexthub/1.0/IContexthub.hal b/contexthub/1.0/IContexthub.hal
new file mode 100644
index 0000000..c0928d5
--- /dev/null
+++ b/contexthub/1.0/IContexthub.hal
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+import IContexthubCallback;
+
+/*
+ * The Context Hub HAL provides an interface to a separate low-power processing
+ * domain that has direct access to contextual information, such as sensors.
+ * Native applications that run within a context hub are known as nanoapps, and
+ * they execute within the Context Hub Runtime Environment (CHRE), which is
+ * standardized via the CHRE API, defined elsewhere.
+ */
+interface IContexthub {
+    /*
+     * Enumerate all available context hubs on the system.
+     *
+     * @return hubs list of hubs on this system.
+     */
+    getHubs() generates (vec<ContextHub> hubs);
+
+    /*
+     * Register a callback for the HAL implementation to send asynchronous
+     * messages to the service from a context hub. There can be a maximum of
+     * one callback registered with the HAL. A call to this function when a
+     * callback has already been registered must override the previous
+     * registration.
+     *
+     * @param hubId    identifier for the hub
+     *        callback an implementation of the IContextHubCallbacks
+     *
+     * @return result OK on success
+     *                BAD_VALUE if parameters are not sane
+     *
+     */
+     registerCallback(uint32_t hubId, IContexthubCallback cb) generates (Result result);
+
+    /**
+     * Send a message to a hub
+     *
+     * @param hubId identifier for hub to send message to
+     *        msg   message to be sent
+     *
+     * @return result OK if successful, error code otherwise
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_FAILED if message send failed
+     */
+    sendMessageToHub(uint32_t hubId, ContextHubMsg msg)
+            generates (Result result);
+
+    /**
+     * Loads a nanoApp. After loading, the nanoApp's init method must be called.
+     * After the init method for nanoApp returns success, this must be indicated
+     * to the service by an asynchronous call to handleTxnResult.
+     *
+     * Loading a nanoapp must not take more than 30 seconds.
+     *
+     * Depending on the implementation, nanoApps loaded via this API may or may
+     * not persist across reboots of the hub. If they do persist, the
+     * implementation must initially place nanoApps in the disabled state upon a
+     * reboot, and not start them until a call is made to enableNanoApp(). In
+     * this case, the app must also be unloaded upon a factory reset of the
+     * device.
+     *
+     * @param hubId identifer of the contextHub
+     *        appBinary contains the binary representation of the nanoApp, plus
+     *                  metadata
+     *        transactionId transactionId for this call
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                TRANSACTION_FAILED if load failed synchronously
+     *
+     */
+    loadNanoApp(uint32_t hubId,
+                NanoAppBinary appBinary,
+                uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Unloads a nanoApp. Before the unload, the apps deinit method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous call to handleTxnResult.
+     *
+     * Unloading a nanoapp must not take more than 5 seconds.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                TRANSACTION_FAILED if unload failed synchronously
+     *
+     */
+    unloadNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Enables a nanoApp. The app's init method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous message.
+     *
+     * Enabling a nanoapp must not take more than 5 seconds.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                FAILED_TRANSACTION if load fails immediately
+     *
+     */
+    enableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Disables a nanoApp. The app's deinit method is called.
+     * After this, success must be indicated to the service through an
+     * asynchronous message.
+     *
+     * Disabling a nanoapp must not take more than 5 seconds.
+     *
+     * @param hubId identifer of the contextHub
+     *        appId appIdentifier returned by the HAL
+     *        msg   message to be sent
+     *
+     * @return result OK if transation started
+     *                BAD_VALUE if parameters are not sane
+     *                TRANSACTION_PENDING if hub is busy with another
+     *                                    load/unload transaction
+     *                FAILED_TRANSACTION if load fails immediately
+     *
+     */
+    disableNanoApp(uint32_t hubId, uint64_t appId, uint32_t transactionId)
+            generates (Result result);
+
+    /**
+     * Queries for Loaded apps on the hub
+     *
+     * @param hubId identifer of the contextHub
+     *
+     * @return apps all nanoApps on the hub.
+     *              All nanoApps that can be modified by the service must
+     *              be returned. A non-modifiable nanoapps must not be
+     *              returned. A modifiable nanoApp is one that can be
+     *              unloaded/disabled/enabled by the service.
+     *
+     */
+    queryApps(uint32_t hubId) generates (Result result);
+};
diff --git a/contexthub/1.0/IContexthubCallback.hal b/contexthub/1.0/IContexthubCallback.hal
new file mode 100644
index 0000000..9a6db4c
--- /dev/null
+++ b/contexthub/1.0/IContexthubCallback.hal
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+interface IContexthubCallback {
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send asynchronous messages back
+     * to the service and registered clients of the ContextHub service.
+     *
+     * @params msg : message
+     *
+     */
+     handleClientMsg(ContextHubMsg msg);
+
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send the response for a
+     * transaction.
+     *
+     * @params txnId : transaction id whose result is being sent
+     *                 passed in by the service at start of transacation.
+     *         result: result of transaction.
+     *
+     */
+     handleTxnResult(uint32_t txnId, TransactionResult result);
+
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send an asynchronous event
+     * to the ContextHub service.
+     *
+     * @params msg : message
+     *
+     */
+     handleHubEvent(AsyncEventType evt);
+
+    /*
+     * This callback is passed by the Contexthub service to the HAL
+     * implementation to allow the HAL to send a notification to the service
+     * that a nanp-app has aborted.
+     * This method must be called when a nanoapp invokes chreAbort(...)).
+     *
+     * @params appId : app identifier
+     *               : abortCode code passed by the nanoApp.
+     *
+     * Also see chreAbort(...)
+     *
+     */
+     handleAppAbort(uint64_t appId, uint32_t abortCode);
+
+     /*
+      * This callback is passed by the Contexthub service to the HAL
+      * implementation to allow the HAL to send information about the
+      * currently loaded and active nanoapps on the hub.
+      *
+      * @params appInfo : vector of HubAppinfo structure for each nanoApp
+      *                   on the hub that can be enabled, disabled and
+      *                   unloaded by the service. Any nanoApps that cannot
+      *                   be controlled by the service must not be reported.
+      *                   All nanoApps that can be controlled by the service
+      *                   must be reported.
+      */
+      handleAppsInfo(vec<HubAppInfo> appInfo);
+};
diff --git a/contexthub/1.0/default/Android.bp b/contexthub/1.0/default/Android.bp
new file mode 100644
index 0000000..7c5f79d
--- /dev/null
+++ b/contexthub/1.0/default/Android.bp
@@ -0,0 +1,33 @@
+/*
+ * 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.contexthub@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Contexthub.cpp"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.contexthub@1.0",
+    ],
+}
diff --git a/contexthub/1.0/default/Android.mk b/contexthub/1.0/default/Android.mk
new file mode 100644
index 0000000..ad40878
--- /dev/null
+++ b/contexthub/1.0/default/Android.mk
@@ -0,0 +1,23 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.contexthub@1.0-service
+LOCAL_INIT_RC := android.hardware.contexthub@1.0-service.rc
+LOCAL_SRC_FILES := \
+        service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+        libbase \
+        libcutils \
+        libdl \
+        libhardware \
+        libhardware_legacy \
+        libhidlbase \
+        libhidltransport \
+        libhwbinder \
+        liblog \
+        libutils \
+        android.hardware.contexthub@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
new file mode 100644
index 0000000..4a6b3f2
--- /dev/null
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -0,0 +1,553 @@
+/*
+ * 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.
+ */
+
+#include "Contexthub.h"
+
+#include <inttypes.h>
+
+#include <log/log.h>
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hardware/context_hub.h>
+#include <sys/endian.h>
+
+#undef LOG_TAG
+#define LOG_TAG "ContextHubHalAdapter"
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_0 {
+namespace implementation {
+
+static constexpr uint64_t ALL_APPS = UINT64_C(0xFFFFFFFFFFFFFFFF);
+
+Contexthub::Contexthub()
+        : mInitCheck(NO_INIT),
+          mContextHubModule(nullptr),
+          mIsTransactionPending(false) {
+    const hw_module_t *module;
+
+    mInitCheck = hw_get_module(CONTEXT_HUB_MODULE_ID, &module);
+
+    if (mInitCheck != OK) {
+        ALOGE("Could not load %s module: %s", CONTEXT_HUB_MODULE_ID, strerror(-mInitCheck));
+    } else if (module == nullptr) {
+        ALOGE("hal returned succes but a null module!");
+        // Assign an error, this should not really happen...
+        mInitCheck = UNKNOWN_ERROR;
+    } else {
+        ALOGI("Loaded Context Hub module");
+        mContextHubModule = reinterpret_cast<const context_hub_module_t *>(module);
+    }
+}
+
+bool Contexthub::setOsAppAsDestination(hub_message_t *msg, int hubId) {
+    if (!isValidHubId(hubId)) {
+        ALOGW("%s: Hub information is null for hubHandle %d",
+              __FUNCTION__,
+              hubId);
+        return false;
+    } else {
+        msg->app_name = mCachedHubInfo[hubId].osAppName;
+        return true;
+    }
+}
+
+Return<void> Contexthub::getHubs(getHubs_cb _hidl_cb) {
+    std::vector<ContextHub> hubs;
+    if (isInitialized()) {
+        const context_hub_t *hubArray = nullptr;
+        size_t numHubs;
+
+        // Explicitly discarding const. HAL method discards it.
+        numHubs = mContextHubModule->get_hubs(const_cast<context_hub_module_t *>(mContextHubModule),
+                                              &hubArray);
+        ALOGI("Context Hub Hal Adapter reports %zu hubs", numHubs);
+
+        mCachedHubInfo.clear();
+
+        for (size_t i = 0; i < numHubs; i++) {
+            CachedHubInformation info;
+            ContextHub c;
+
+            c.hubId = hubArray[i].hub_id;
+            c.name = hubArray[i].name;
+            c.vendor = hubArray[i].vendor;
+            c.toolchain = hubArray[i].toolchain;
+            c.toolchainVersion = hubArray[i].toolchain_version;
+            c.platformVersion = hubArray[i].platform_version;
+            c.maxSupportedMsgLen = hubArray[i].max_supported_msg_len;
+            c.peakMips = hubArray[i].peak_mips;
+            c.peakPowerDrawMw = hubArray[i].peak_power_draw_mw;
+            c.stoppedPowerDrawMw = hubArray[i].stopped_power_draw_mw;
+            c.sleepPowerDrawMw = hubArray[i].sleep_power_draw_mw;
+
+            info.callBack = nullptr;
+            info.osAppName = hubArray[i].os_app_name;
+            mCachedHubInfo[hubArray[i].hub_id] = info;
+
+            hubs.push_back(c);
+        }
+    } else {
+        ALOGW("Context Hub Hal Adapter not initialized");
+    }
+
+    _hidl_cb(hubs);
+    return Void();
+}
+
+bool Contexthub::isValidHubId(uint32_t hubId) {
+    if (!mCachedHubInfo.count(hubId)) {
+        ALOGW("Hub information not found for hubId %" PRIu32, hubId);
+        return false;
+    } else {
+        return true;
+    }
+}
+
+sp<IContexthubCallback> Contexthub::getCallBackForHubId(uint32_t hubId) {
+    if (!isValidHubId(hubId)) {
+        return nullptr;
+    } else {
+        return mCachedHubInfo[hubId].callBack;
+    }
+}
+
+Return<Result> Contexthub::sendMessageToHub(uint32_t hubId,
+                                            const ContextHubMsg &msg) {
+    if (!isInitialized()) {
+        return Result::NOT_INIT;
+    }
+
+    if (!isValidHubId(hubId) || msg.msg.size() > UINT32_MAX) {
+        return Result::BAD_PARAMS;
+    }
+
+    hub_message_t txMsg = {
+        .app_name.id = msg.appName,
+        .message_type = msg.msgType,
+        .message_len = static_cast<uint32_t>(msg.msg.size()), // Note the check above
+        .message = static_cast<const uint8_t *>(msg.msg.data()),
+    };
+
+    ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
+          txMsg.message_type,
+          txMsg.message_len,
+          txMsg.app_name.id);
+
+    if(mContextHubModule->send_message(hubId, &txMsg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    }
+
+    return Result::OK;
+}
+
+Return<Result> Contexthub::reboot(uint32_t hubId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    msg.message_type = CONTEXT_HUB_OS_REBOOT;
+    msg.message_len = 0;
+    msg.message = nullptr;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::registerCallback(uint32_t hubId,
+                                            const sp<IContexthubCallback> &cb) {
+    Return<Result> retVal = Result::BAD_PARAMS;
+
+    if (!isInitialized()) {
+        // Not initilalized
+        ALOGW("Context hub not initialized successfully");
+        retVal = Result::NOT_INIT;
+    } else if (!isValidHubId(hubId)) {
+        // Initialized, but hubId is  not valid
+        retVal = Result::BAD_PARAMS;
+    } else if (mContextHubModule->subscribe_messages(hubId,
+                                                     contextHubCb,
+                                                     this) == 0) {
+        // Initialized && valid hub && subscription successful
+        retVal = Result::OK;
+        mCachedHubInfo[hubId].callBack = cb;
+    } else {
+        // Initalized && valid hubId - but subscription unsuccessful
+        // This is likely an internal error in the HAL implementation, but we
+        // cannot add more information.
+        ALOGW("Could not subscribe to the hub for callback");
+        retVal = Result::UNKNOWN_FAILURE;
+    }
+
+    return retVal;
+}
+
+static bool isValidOsStatus(const uint8_t *msg,
+                            size_t msgLen,
+                            status_response_t *rsp) {
+    // Workaround a bug in some HALs
+    if (msgLen == 1) {
+        rsp->result = msg[0];
+        return true;
+    }
+
+    if (msg == nullptr || msgLen != sizeof(*rsp)) {
+        ALOGI("Received invalid response (is null : %d, size %zu)",
+              msg == nullptr ? 1 : 0,
+              msgLen);
+        return false;
+    }
+
+    memcpy(rsp, msg, sizeof(*rsp));
+
+    // No sanity checks on return values
+    return true;
+}
+
+int Contexthub::handleOsMessage(sp<IContexthubCallback> cb,
+                                uint32_t msgType,
+                                const uint8_t *msg,
+                                int msgLen) {
+    int retVal = -1;
+
+
+    switch(msgType) {
+        case CONTEXT_HUB_APPS_ENABLE:
+        case CONTEXT_HUB_APPS_DISABLE:
+        case CONTEXT_HUB_LOAD_APP:
+        case CONTEXT_HUB_UNLOAD_APP:
+        {
+            struct status_response_t rsp;
+            TransactionResult result;
+            if (isValidOsStatus(msg, msgLen, &rsp) && rsp.result == 0) {
+                retVal = 0;
+                result = TransactionResult::SUCCESS;
+            } else {
+                result = TransactionResult::FAILURE;
+            }
+
+            if (cb != nullptr) {
+                cb->handleTxnResult(mTransactionId, result);
+            }
+            retVal = 0;
+            mIsTransactionPending = false;
+            break;
+        }
+
+        case CONTEXT_HUB_QUERY_APPS:
+        {
+            std::vector<HubAppInfo> apps;
+            int numApps = msgLen / sizeof(hub_app_info);
+            const hub_app_info *unalignedInfoAddr = reinterpret_cast<const hub_app_info *>(msg);
+
+            for (int i = 0; i < numApps; i++) {
+                hub_app_info query_info;
+                memcpy(&query_info, &unalignedInfoAddr[i], sizeof(query_info));
+                HubAppInfo app;
+                app.appId = query_info.app_name.id;
+                app.version = query_info.version;
+                // TODO :: Add memory ranges
+
+                apps.push_back(app);
+            }
+
+            if (cb != nullptr) {
+                cb->handleAppsInfo(apps);
+            }
+            retVal = 0;
+            break;
+        }
+
+        case CONTEXT_HUB_QUERY_MEMORY:
+        {
+            // Deferring this use
+            retVal = 0;
+            break;
+        }
+
+        case CONTEXT_HUB_OS_REBOOT:
+        {
+            mIsTransactionPending = false;
+            if (cb != nullptr) {
+                cb->handleHubEvent(AsyncEventType::RESTARTED);
+            }
+            retVal = 0;
+            break;
+        }
+
+        default:
+        {
+            retVal = -1;
+            break;
+        }
+      }
+
+      return retVal;
+}
+
+int Contexthub::contextHubCb(uint32_t hubId,
+                             const struct hub_message_t *rxMsg,
+                             void *cookie) {
+    Contexthub *obj = static_cast<Contexthub *>(cookie);
+
+    if (rxMsg == nullptr) {
+        ALOGW("Ignoring NULL message");
+        return -1;
+    }
+
+    if (!obj->isValidHubId(hubId)) {
+        ALOGW("Invalid hub Id %" PRIu32, hubId);
+        return -1;
+    }
+
+    sp<IContexthubCallback> cb = obj->getCallBackForHubId(hubId);
+
+    if (cb == nullptr) {
+        // This should not ever happen
+        ALOGW("No callback registered, returning");
+        return -1;
+    }
+
+    if (rxMsg->message_type < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) {
+        obj->handleOsMessage(cb,
+                             rxMsg->message_type,
+                             static_cast<const uint8_t *>(rxMsg->message),
+                             rxMsg->message_len);
+    } else {
+        ContextHubMsg msg;
+
+        msg.appName = rxMsg->app_name.id;
+        msg.msgType = rxMsg->message_type;
+        msg.msg = std::vector<uint8_t>(static_cast<const uint8_t *>(rxMsg->message),
+                                       static_cast<const uint8_t *>(rxMsg->message) +
+                                       rxMsg->message_len);
+
+        cb->handleClientMsg(msg);
+    }
+
+    return 0;
+}
+
+Return<Result> Contexthub::unloadNanoApp(uint32_t hubId,
+                                         uint64_t appId,
+                                         uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_disable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_UNLOAD_APP;
+    msg.message_len = sizeof(req);
+    msg.message = &req;
+    req.app_name.id = appId;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::loadNanoApp(uint32_t hubId,
+                                       const NanoAppBinary& appBinary,
+                                       uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t hubMsg;
+
+    if (setOsAppAsDestination(&hubMsg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    // Data from the nanoapp header is passed through HIDL as explicit fields,
+    // but the legacy HAL expects it prepended to the binary, therefore we must
+    // reconstruct it here prior to passing to the legacy HAL.
+    uint32_t targetChreApiVersion =
+        (appBinary.targetChreApiMajorVersion << 24) |
+        (appBinary.targetChreApiMinorVersion << 16);
+    const struct nano_app_binary_t header = {
+        .header_version = htole32(1),
+        .magic          = htole32(NANOAPP_MAGIC),
+        .app_id.id      = htole64(appBinary.appId),
+        .app_version    = htole32(appBinary.appVersion),
+        .flags          = htole32(appBinary.flags),
+        .hw_hub_type    = htole64(0),
+        .reserved[0]    = htole32(targetChreApiVersion),
+        .reserved[1]    = 0,
+    };
+    const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);
+
+    std::vector<uint8_t> binaryWithHeader(appBinary.customBinary);
+    binaryWithHeader.insert(binaryWithHeader.begin(),
+                            headerBytes,
+                            headerBytes + sizeof(header));
+
+    hubMsg.message_type = CONTEXT_HUB_LOAD_APP;
+    hubMsg.message_len = binaryWithHeader.size();
+    hubMsg.message = binaryWithHeader.data();
+
+    if (mContextHubModule->send_message(hubId, &hubMsg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::enableNanoApp(uint32_t hubId,
+                                         uint64_t appId,
+                                         uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_enable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_APPS_ENABLE;
+    msg.message_len = sizeof(req);
+    req.app_name.id = appId;
+    msg.message = &req;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::disableNanoApp(uint32_t hubId,
+                                          uint64_t appId,
+                                          uint32_t transactionId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    if (mIsTransactionPending) {
+        return Result::TRANSACTION_PENDING;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        return Result::BAD_PARAMS;
+    }
+
+    struct apps_disable_request_t req;
+
+    msg.message_type = CONTEXT_HUB_APPS_DISABLE;
+    msg.message_len = sizeof(req);
+    req.app_name.id = appId;
+    msg.message = &req;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        return Result::TRANSACTION_FAILED;
+    } else {
+        mTransactionId = transactionId;
+        mIsTransactionPending = true;
+        return Result::OK;
+    }
+}
+
+Return<Result> Contexthub::queryApps(uint32_t hubId) {
+    if (!isInitialized()) {
+      return Result::NOT_INIT;
+    }
+
+    hub_message_t msg;
+
+    if (setOsAppAsDestination(&msg, hubId) == false) {
+        ALOGW("Could not find hubId %" PRIu32, hubId);
+        return Result::BAD_PARAMS;
+    }
+
+    query_apps_request_t payload;
+    payload.app_name.id = ALL_APPS; // TODO : Pass this in as a parameter
+    msg.message = &payload;
+    msg.message_len = sizeof(payload);
+    msg.message_type = CONTEXT_HUB_QUERY_APPS;
+
+    if(mContextHubModule->send_message(hubId, &msg) != 0) {
+        ALOGW("Query Apps sendMessage failed");
+        return Result::TRANSACTION_FAILED;
+    }
+
+    return Result::OK;
+}
+
+bool Contexthub::isInitialized() {
+    return (mInitCheck == OK && mContextHubModule != nullptr);
+}
+
+IContexthub *HIDL_FETCH_IContexthub(const char * halName) {
+    ALOGI("%s Called for %s", __FUNCTION__, halName);
+    Contexthub *contexthub = new Contexthub;
+
+    if (!contexthub->isInitialized()) {
+        delete contexthub;
+        contexthub = nullptr;
+    }
+
+    return contexthub;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
diff --git a/contexthub/1.0/default/Contexthub.h b/contexthub/1.0/default/Contexthub.h
new file mode 100644
index 0000000..236e079
--- /dev/null
+++ b/contexthub/1.0/default/Contexthub.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
+#define ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
+
+#include <unordered_map>
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hardware/context_hub.h>
+
+namespace android {
+namespace hardware {
+namespace contexthub {
+namespace V1_0 {
+namespace implementation {
+
+struct Contexthub : public ::android::hardware::contexthub::V1_0::IContexthub {
+    Contexthub();
+
+    Return<void> getHubs(getHubs_cb _hidl_cb) override;
+
+    Return<Result> registerCallback(uint32_t hubId,
+                                    const sp<IContexthubCallback> &cb) override;
+
+    Return<Result> sendMessageToHub(uint32_t hubId,
+                                    const ContextHubMsg &msg) override;
+
+    Return<Result> loadNanoApp(uint32_t hubId,
+                               const NanoAppBinary& appBinary,
+                               uint32_t transactionId) override;
+
+    Return<Result> unloadNanoApp(uint32_t hubId,
+                                 uint64_t appId,
+                                 uint32_t transactionId) override;
+
+    Return<Result> enableNanoApp(uint32_t hubId,
+                                 uint64_t appId,
+                                 uint32_t transactionId) override;
+
+    Return<Result> disableNanoApp(uint32_t hubId,
+                                  uint64_t appId,
+                                  uint32_t transactionId) override;
+
+    Return<Result> queryApps(uint32_t hubId) override;
+
+    Return<Result> reboot(uint32_t hubId);
+
+    bool isInitialized();
+
+private:
+
+    struct CachedHubInformation{
+        struct hub_app_name_t osAppName;
+        sp<IContexthubCallback> callBack;
+    };
+
+    status_t mInitCheck;
+    const struct context_hub_module_t *mContextHubModule;
+    std::unordered_map<uint32_t, CachedHubInformation> mCachedHubInfo;
+
+    sp<IContexthubCallback> mCb;
+    bool mIsTransactionPending;
+    uint32_t mTransactionId;
+
+    bool isValidHubId(uint32_t hubId);
+
+    sp<IContexthubCallback> getCallBackForHubId(uint32_t hubId);
+
+    int handleOsMessage(sp<IContexthubCallback> cb,
+                        uint32_t msgType,
+                        const uint8_t *msg,
+                        int msgLen);
+
+    static int contextHubCb(uint32_t hubId,
+                            const struct hub_message_t *rxMsg,
+                            void *cookie);
+
+    bool setOsAppAsDestination(hub_message_t *msg, int hubId);
+
+    DISALLOW_COPY_AND_ASSIGN(Contexthub);
+};
+
+extern "C" IContexthub *HIDL_FETCH_IContexthub(const char *name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace contexthub
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONTEXTHUB_V1_0_CONTEXTHUB_H_
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
new file mode 100644
index 0000000..8dba85f
--- /dev/null
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -0,0 +1,4 @@
+service contexthub-hal-1-0 /system/bin/hw/android.hardware.contexthub@1.0-service
+    class hal
+    user system
+    group system
diff --git a/contexthub/1.0/default/service.cpp b/contexthub/1.0/default/service.cpp
new file mode 100644
index 0000000..db9a4e7
--- /dev/null
+++ b/contexthub/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.contexthub@1.0-service"
+
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::contexthub::V1_0::IContexthub;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IContexthub>("context_hub");
+}
diff --git a/contexthub/1.0/types.hal b/contexthub/1.0/types.hal
new file mode 100644
index 0000000..4950627
--- /dev/null
+++ b/contexthub/1.0/types.hal
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+package android.hardware.contexthub@1.0;
+
+enum Result : uint32_t {
+    OK,                  // Success
+    UNKNOWN_FAILURE,     // Failure, unknown reason
+    BAD_PARAMS,          // Parameters not sane
+    NOT_INIT,            // Not initialized
+    TRANSACTION_FAILED,  // Transaction failed
+    TRANSACTION_PENDING, // Pending transaction, cannot accept a new request
+};
+
+enum NanoAppFlags : uint32_t {
+    SIGNED    = 1 << 0,
+    ENCRYPTED = 1 << 1,
+};
+
+struct NanoAppBinary {
+    uint64_t appId;            // Nanoapp identifier
+    uint32_t appVersion;       // Version of the app (semantics defined by app)
+    bitfield<NanoAppFlags> flags;
+
+    // The version of the CHRE API that this nanoApp was compiled against. See
+    // the CHRE API header file chre/version.h for more information. The hub
+    // implementation must use this to confirm compatibility before loading
+    // this nanoApp.
+    uint8_t targetChreApiMajorVersion;
+    uint8_t targetChreApiMinorVersion;
+
+    // Implementation-specific binary nanoapp data. This does not include the
+    // common nanoapp header that contains the app ID, etc., as this data is
+    // explicitly passed through the other fields in this struct.
+    vec<uint8_t> customBinary;
+};
+
+enum SensorType : uint32_t {
+    RESERVED,
+    ACCELEROMETER,
+    GYROSCOPE,
+    MAGNETOMETER,
+    BAROMETER,
+    PROXIMITY_SENSOR,
+    AMBIENT_LIGHT_SENSOR,
+    STATIONARY_DETECT,
+    INSTANT_MOTION_DETECT,
+
+    GPS = 0x100,
+    // Reserving this space for variants on GPS
+
+    WIFI = 0x200,
+    // Reserving this space for variants on WIFI
+
+    AUDIO = 0x300,
+    // Reserving this space for variants on Audio
+
+    CAMERA = 0x400,
+    // Reserving this space for variants on Camera
+
+    BLE = 0x500,
+    // Reserving this space for variants on Bluetooth Low Energy
+
+    WWAN = 0x600,
+    // Reserving this space for variants on WWAN
+
+    PRIVATE_SENSOR_BASE = 0x10000,
+    // Sensor types beyond PRIVATE_SENSOR_BASE are custom types
+};
+
+struct PhysicalSensor{
+    SensorType sensorType;       // From the definitions above eg: 100
+    string type;                 // Type as a string. eg: "GPS"
+    string name;                 // Identifier eg: "Bosch BMI160"
+    string vendor;               // Vendor : eg "STM"
+    uint32_t version;            // Version : eg 0x1001
+    uint32_t fifoReservedCount;  // Batching possible in hardware. Please
+                                 // note that here hardware does not include
+                                 // the context hub itself. Thus, this
+                                 // definition may be different from say the
+                                 // number advertised in the sensors HAL
+                                 // which allows for batching in a hub.
+    uint32_t fifoMaxCount;       // Maximum number of batchable events.
+    uint64_t minDelayMs;         // In milliseconds, corresponding to highest
+                                 // sampling freq.
+    uint64_t maxDelayMs;         // In milliseconds, corresponds to minimum
+                                 // sampling frequency
+    float peakPowerMw;           // At max frequency & no batching, power
+                                 // in milliwatts
+};
+
+struct ContextHub {
+    string name;                // Descriptive name eg: "Awesome Hub #1"
+    string vendor;              // Hub hardware vendor eg: "Qualcomm"
+    string toolchain;           // Toolchain to make binaries eg: "gcc ARM"
+    uint32_t platformVersion;   // Version of the hardware : eg 0x20
+    uint32_t toolchainVersion;  // Version of the toolchain : eg: 0x484
+    uint32_t hubId;             // A device unique ID for this hub
+
+    float peakMips;             // Peak MIPS platform can deliver
+    float stoppedPowerDrawMw;   // If stopped, retention power, milliwatts
+    float sleepPowerDrawMw;     // If sleeping, retention power, milliwatts
+    float peakPowerDrawMw;      // For a busy CPU, power in milliwatts
+
+    vec<PhysicalSensor> connectedSensors; // Array of connected sensors
+
+    uint32_t maxSupportedMsgLen;// This is the maximum size of the message that can
+                                // be sent to the hub in one chunk (in bytes)
+
+    // Machine-readable CHRE platform ID, returned to nanoapps in the CHRE API
+    // function call chreGetPlatformId(). This field pairs with
+    // chreApiMajorVersion, chreApiMinorVersion, and chrePatchVersion to fully
+    // specify the CHRE implementation version. See also the CHRE API header
+    // file chre/version.h.
+    uint64_t chrePlatformId;
+
+    // The version of the CHRE implementation returned to nanoApps in the CHRE
+    // API function call chreGetVersion(). The major and minor version specify
+    // the implemented version of the CHRE API, while the patch version
+    // describes the implementation version within the scope of the platform
+    // ID. See also the CHRE API header file chre/version.h.
+    uint8_t chreApiMajorVersion;
+    uint8_t chreApiMinorVersion;
+    uint16_t chrePatchVersion;
+};
+
+enum HostEndPoint : uint16_t {
+    BROADCAST = 0xFFFF, // The message endpoint is a broadcast end point.
+                        // This value must never be used for a message from
+                        // the host to the hub.
+                        // If BROADCAST is specified as a destination for a
+                        // message from the context hub to the ContextHub
+                        // service, the message must be broadcast to all
+                        // registered clients by the Context Hub service.
+    UNSPECIFIED = 0xFFFE, // The message endpoint is unspecified. This value
+                          // must not be used for messages from the hub to host.
+                          // This value may be used for messages from the host
+                          // to the hub.
+};
+
+struct ContextHubMsg {
+    uint64_t appName;      // Intended recipient (appId)
+    uint16_t hostEndPoint; // identifier for the endpoint. (also see enum HostEndPoint)
+    uint32_t msgType;      // Identifier for message
+    vec<uint8_t> msg;      // Message body
+};
+
+enum HubMemoryType : uint32_t {
+    MAIN      = 0, // Main memory
+    SECONDARY = 1, // Secondary memory
+    TCM       = 2, // Tightly coupled memory
+};
+
+enum HubMemoryFlag : uint32_t {
+    READ  = 1 << 0, // Readable
+    WRITE = 1 << 1, // Writable
+    EXEC  = 1 << 2, // Executable
+};
+
+struct MemRange {
+    uint32_t totalBytes; // Total capacity in bytes
+    uint32_t freeBytes;  // Free capacity in bytes
+    HubMemoryType type;  // Type of memory, see HubMemoryType
+    bitfield<HubMemoryFlag> flags;
+};
+
+enum AsyncEventType : uint32_t {
+    RESTARTED = 1,   // Hub restarted unexpectedly
+};
+
+enum TransactionResult : int32_t {
+    SUCCESS,      // Successful completion of transaction
+    FAILURE,      // Failed transaction
+};
+
+struct HubAppInfo {
+    uint64_t appId;         // Identifier of the app
+    uint32_t version;       // Version of the app
+    vec<MemRange> memUsage; // Memory used by this app
+    bool enabled;           // true if the app is currently enabled and running,
+                            // or false if in the loaded but disabled state
+};
+
diff --git a/contexthub/1.0/vts/Android.mk b/contexthub/1.0/vts/Android.mk
new file mode 100644
index 0000000..266884b
--- /dev/null
+++ b/contexthub/1.0/vts/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+contexthub-vts-path := $(LOCAL_PATH)
+
+include $(contexthub-vts-path)/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
diff --git a/contexthub/1.0/vts/Contexthub.vts b/contexthub/1.0/vts/Contexthub.vts
new file mode 100644
index 0000000..b4e42f5
--- /dev/null
+++ b/contexthub/1.0/vts/Contexthub.vts
@@ -0,0 +1,147 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IContexthub"
+
+package: "android.hardware.contexthub"
+
+import: "android.hardware.contexthub@1.0::IContexthubCallback"
+import: "android.hardware.contexthub@1.0::types"
+
+interface: {
+    api: {
+        name: "getHubs"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::contexthub::V1_0::ContextHub"
+            }
+        }
+    }
+
+    api: {
+        name: "registerCallback"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "IContexthubCallback"
+            is_callback: true
+        }
+    }
+
+    api: {
+        name: "sendMessageToHub"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+        }
+    }
+
+    api: {
+        name: "loadNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::NanoAppBinary"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "unloadNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "enableNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "disableNanoApp"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "queryApps"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+}
diff --git a/contexthub/1.0/vts/ContexthubCallback.vts b/contexthub/1.0/vts/ContexthubCallback.vts
new file mode 100644
index 0000000..c3784e8
--- /dev/null
+++ b/contexthub/1.0/vts/ContexthubCallback.vts
@@ -0,0 +1,61 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IContexthubCallback"
+
+package: "android.hardware.contexthub"
+
+import: "android.hardware.contexthub@1.0::types"
+
+interface: {
+    api: {
+        name: "handleClientMsg"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+        }
+    }
+
+    api: {
+        name: "handleTxnResult"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::TransactionResult"
+        }
+    }
+
+    api: {
+        name: "handleHubEvent"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::contexthub::V1_0::AsyncEventType"
+        }
+    }
+
+    api: {
+        name: "handleAppAbort"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "handleAppsInfo"
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::contexthub::V1_0::HubAppInfo"
+            }
+        }
+    }
+
+}
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..e78898e
--- /dev/null
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -0,0 +1,38 @@
+//
+// 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: "contexthub_hidl_hal_test",
+    gtest: true,
+    srcs: ["contexthub_hidl_hal_test.cpp"],
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.contexthub@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage",
+    ],
+}
+
diff --git a/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp b/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp
new file mode 100644
index 0000000..e4dea4f
--- /dev/null
+++ b/contexthub/1.0/vts/functional/contexthub_hidl_hal_test.cpp
@@ -0,0 +1,388 @@
+/*
+ * 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 "contexthub_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/contexthub/1.0/IContexthub.h>
+#include <android/hardware/contexthub/1.0/IContexthubCallback.h>
+#include <android/hardware/contexthub/1.0/types.h>
+#include <android/log.h>
+#include <gtest/gtest.h>
+
+#include <cinttypes>
+#include <future>
+#include <utility>
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::contexthub::V1_0::AsyncEventType;
+using ::android::hardware::contexthub::V1_0::ContextHub;
+using ::android::hardware::contexthub::V1_0::ContextHubMsg;
+using ::android::hardware::contexthub::V1_0::HubAppInfo;
+using ::android::hardware::contexthub::V1_0::IContexthub;
+using ::android::hardware::contexthub::V1_0::IContexthubCallback;
+using ::android::hardware::contexthub::V1_0::NanoAppBinary;
+using ::android::hardware::contexthub::V1_0::Result;
+using ::android::hardware::contexthub::V1_0::TransactionResult;
+using ::android::sp;
+
+#define CONTEXTHUB_SERVICE_NAME "contexthub"
+
+#define ASSERT_OK(result) ASSERT_EQ(result, Result::OK)
+#define EXPECT_OK(result) EXPECT_EQ(result, Result::OK)
+
+namespace {
+
+// App ID with vendor "GoogT" (Google Testing), app identifier 0x555555. This
+// app ID is reserved and must never appear in the list of loaded apps.
+constexpr uint64_t kNonExistentAppId = 0x476f6f6754555555;
+
+// Helper that does explicit conversion of an enum class to its underlying/base
+// type. Useful for stream output of enum values.
+template<typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(
+    EnumType value) {
+  return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+// Synchronously queries IContexthub::getHubs() and returns the result
+hidl_vec<ContextHub> getHubsSync(sp<IContexthub> hubApi) {
+  hidl_vec<ContextHub> hubList;
+  std::promise<void> barrier;
+
+  hubApi->getHubs([&hubList, &barrier](const hidl_vec<ContextHub>& hubs) {
+    hubList = hubs;
+    barrier.set_value();
+  });
+  barrier.get_future().wait_for(std::chrono::seconds(1));
+
+  return hubList;
+}
+
+// Gets a list of valid hub IDs in the system
+std::vector<uint32_t> getHubIds() {
+  static std::vector<uint32_t> hubIds;
+
+  if (hubIds.size() == 0) {
+    sp<IContexthub> hubApi = IContexthub::getService(CONTEXTHUB_SERVICE_NAME);
+
+    if (hubApi != nullptr) {
+      for (ContextHub hub : getHubsSync(hubApi)) {
+        hubIds.push_back(hub.hubId);
+      }
+    }
+  }
+
+  ALOGD("Running tests against all %zu reported hubs", hubIds.size());
+  return hubIds;
+}
+
+// Base test fixture that initializes the HAL and makes the context hub API
+// handle available
+class ContexthubHidlTestBase : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    hubApi = IContexthub::getService(CONTEXTHUB_SERVICE_NAME);
+    ASSERT_NE(hubApi, nullptr);
+
+    // getHubs() must be called at least once for proper initialization of the
+    // HAL implementation
+    getHubsSync(hubApi);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IContexthub> hubApi;
+};
+
+// Test fixture parameterized by hub ID
+class ContexthubHidlTest : public ContexthubHidlTestBase,
+                           public ::testing::WithParamInterface<uint32_t> {
+ public:
+  uint32_t getHubId() {
+    return GetParam();
+  }
+
+  Result registerCallback(sp<IContexthubCallback> cb) {
+    Result result = hubApi->registerCallback(getHubId(), cb);
+    ALOGD("Registered callback, result %" PRIu32, result);
+    return result;
+  }
+};
+
+// Base callback implementation that just logs all callbacks by default
+class ContexthubCallbackBase : public IContexthubCallback {
+ public:
+  virtual Return<void> handleClientMsg(const ContextHubMsg& /*msg*/) override {
+    ALOGD("Got client message callback");
+    return Void();
+  }
+
+  virtual Return<void> handleTxnResult(
+      uint32_t txnId, TransactionResult result) override {
+    ALOGD("Got transaction result callback for txnId %" PRIu32 " with result %"
+          PRId32, txnId, result);
+    return Void();
+  }
+
+  virtual Return<void> handleHubEvent(AsyncEventType evt) override {
+    ALOGD("Got hub event callback for event type %" PRIu32, evt);
+    return Void();
+  }
+
+  virtual Return<void> handleAppAbort(uint64_t appId, uint32_t abortCode)
+      override {
+    ALOGD("Got app abort notification for appId 0x%" PRIx64 " with abort code "
+          "0x%" PRIx32, appId, abortCode);
+    return Void();
+  }
+
+  virtual Return<void> handleAppsInfo(const hidl_vec<HubAppInfo>& /*appInfo*/)
+      override {
+    ALOGD("Got app info callback");
+    return Void();
+  }
+};
+
+// Wait for a callback to occur (signaled by the given future) up to the
+// provided timeout. If the future is invalid or the callback does not come
+// within the given time, returns false.
+template<class ReturnType>
+bool waitForCallback(
+    std::future<ReturnType> future,
+    ReturnType *result,
+    std::chrono::milliseconds timeout = std::chrono::seconds(5)) {
+  auto expiration = std::chrono::system_clock::now() + timeout;
+
+  EXPECT_NE(result, nullptr);
+  EXPECT_TRUE(future.valid());
+  if (result != nullptr && future.valid()) {
+    std::future_status status = future.wait_until(expiration);
+    EXPECT_NE(status, std::future_status::timeout)
+        << "Timed out waiting for callback";
+
+    if (status == std::future_status::ready) {
+      *result = future.get();
+      return true;
+    }
+  }
+
+  return false;
+}
+
+// Ensures that the metadata reported in getHubs() is sane
+TEST_F(ContexthubHidlTestBase, TestGetHubs) {
+  hidl_vec<ContextHub> hubs = getHubsSync(hubApi);
+  ALOGD("System reports %zu hubs", hubs.size());
+
+  for (ContextHub hub : hubs) {
+    ALOGD("Checking hub ID %" PRIu32, hub.hubId);
+
+    EXPECT_FALSE(hub.name.empty());
+    EXPECT_FALSE(hub.vendor.empty());
+    EXPECT_FALSE(hub.toolchain.empty());
+    EXPECT_GT(hub.peakMips, 0);
+    EXPECT_GE(hub.stoppedPowerDrawMw, 0);
+    EXPECT_GE(hub.sleepPowerDrawMw, 0);
+    EXPECT_GT(hub.peakPowerDrawMw, 0);
+
+    // Minimum 128 byte MTU as required by CHRE API v1.0
+    EXPECT_GE(hub.maxSupportedMsgLen, UINT32_C(128));
+  }
+}
+
+TEST_P(ContexthubHidlTest, TestRegisterCallback) {
+  ALOGD("TestRegisterCallback called, hubId %" PRIu32, getHubId());
+  ASSERT_OK(registerCallback(new ContexthubCallbackBase()));
+}
+
+TEST_P(ContexthubHidlTest, TestRegisterNullCallback) {
+  ALOGD("TestRegisterNullCallback called, hubId %" PRIu32, getHubId());
+  ASSERT_OK(registerCallback(nullptr));
+}
+
+// Helper callback that puts the async appInfo callback data into a promise
+class QueryAppsCallback : public ContexthubCallbackBase {
+ public:
+  virtual Return<void> handleAppsInfo(const hidl_vec<HubAppInfo>& appInfo)
+      override {
+    ALOGD("Got app info callback with %zu apps", appInfo.size());
+    promise.set_value(appInfo);
+    return Void();
+  }
+
+  std::promise<hidl_vec<HubAppInfo>> promise;
+};
+
+// Calls queryApps() and checks the returned metadata
+TEST_P(ContexthubHidlTest, TestQueryApps) {
+  ALOGD("TestQueryApps called, hubId %u", getHubId());
+  sp<QueryAppsCallback> cb = new QueryAppsCallback();
+  ASSERT_OK(registerCallback(cb));
+
+  Result result = hubApi->queryApps(getHubId());
+  ASSERT_OK(result);
+
+  ALOGD("Waiting for app info callback");
+  hidl_vec<HubAppInfo> appList;
+  ASSERT_TRUE(waitForCallback(cb->promise.get_future(), &appList));
+  for (const HubAppInfo &appInfo : appList) {
+    EXPECT_NE(appInfo.appId, UINT64_C(0));
+    EXPECT_NE(appInfo.appId, kNonExistentAppId);
+  }
+}
+
+// Helper callback that puts the TransactionResult for the expectedTxnId into a
+// promise
+class TxnResultCallback : public ContexthubCallbackBase {
+ public:
+  virtual Return<void> handleTxnResult(
+      uint32_t txnId, TransactionResult result) override {
+    ALOGD("Got transaction result callback for txnId %" PRIu32 " (expecting %"
+          PRIu32 ") with result %" PRId32, txnId, expectedTxnId, result);
+    if (txnId == expectedTxnId) {
+      promise.set_value(result);
+    }
+    return Void();
+  }
+
+  uint32_t expectedTxnId = 0;
+  std::promise<TransactionResult> promise;
+};
+
+// Parameterized fixture that sets the callback to TxnResultCallback
+class ContexthubTxnTest : public ContexthubHidlTest {
+ public:
+  virtual void SetUp() override {
+    ContexthubHidlTest::SetUp();
+    ASSERT_OK(registerCallback(cb));
+  }
+
+  sp<TxnResultCallback> cb = new TxnResultCallback();
+};
+
+
+// Checks cases where the hub implementation is expected to return an error, but
+// that error can be returned either synchronously or in the asynchronous
+// transaction callback. Returns an AssertionResult that can be used in
+// ASSERT/EXPECT_TRUE. Allows checking the sync result against 1 additional
+// allowed error code apart from OK and TRANSACTION_FAILED, which are always
+// allowed.
+::testing::AssertionResult checkFailureSyncOrAsync(
+    Result result, Result allowedSyncResult,
+    std::future<TransactionResult>&& future) {
+  if (result == Result::OK) {
+    // No error reported synchronously - this is OK, but then we should get an
+    // async callback with a failure status
+    TransactionResult asyncResult;
+    if (!waitForCallback(std::forward<std::future<TransactionResult>>(future),
+                         &asyncResult)) {
+      return ::testing::AssertionFailure()
+          << "Got successful sync result, then failed to receive async cb";
+    } else if (asyncResult == TransactionResult::SUCCESS) {
+      return ::testing::AssertionFailure()
+          << "Got successful sync result, then unexpected successful async "
+             "result";
+    }
+  } else if (result != allowedSyncResult &&
+             result != Result::TRANSACTION_FAILED) {
+    return ::testing::AssertionFailure() << "Got sync result "
+        << asBaseType(result) << ", expected TRANSACTION_FAILED or "
+        << asBaseType(allowedSyncResult);
+  }
+
+  return ::testing::AssertionSuccess();
+}
+
+TEST_P(ContexthubTxnTest, TestSendMessageToNonExistentNanoApp) {
+  ContextHubMsg msg;
+  msg.appName = kNonExistentAppId;
+  msg.msgType = 1;
+  msg.msg.resize(4);
+  std::fill(msg.msg.begin(), msg.msg.end(), 0);
+
+  ALOGD("Sending message to non-existent nanoapp");
+  Result result = hubApi->sendMessageToHub(getHubId(), msg);
+  if (result != Result::OK &&
+      result != Result::BAD_PARAMS &&
+      result != Result::TRANSACTION_FAILED) {
+    FAIL() << "Got result " << asBaseType(result) << ", expected OK, BAD_PARAMS"
+        << ", or TRANSACTION_FAILED";
+  }
+}
+
+TEST_P(ContexthubTxnTest, TestLoadEmptyNanoApp) {
+  cb->expectedTxnId = 0123;
+  NanoAppBinary emptyApp;
+
+  emptyApp.appId = kNonExistentAppId;
+  emptyApp.appVersion = 1;
+  emptyApp.flags = 0;
+  emptyApp.targetChreApiMajorVersion = 1;
+  emptyApp.targetChreApiMinorVersion = 0;
+
+  ALOGD("Loading empty nanoapp");
+  Result result = hubApi->loadNanoApp(getHubId(), emptyApp, cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestUnloadNonexistentNanoApp) {
+  cb->expectedTxnId = 1234;
+
+  ALOGD("Unloading nonexistent nanoapp");
+  Result result = hubApi->unloadNanoApp(getHubId(), kNonExistentAppId,
+                                        cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestEnableNonexistentNanoApp) {
+  cb->expectedTxnId = 2345;
+
+  ALOGD("Enabling nonexistent nanoapp");
+  Result result = hubApi->enableNanoApp(getHubId(), kNonExistentAppId,
+                                        cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+TEST_P(ContexthubTxnTest, TestDisableNonexistentNanoApp) {
+  cb->expectedTxnId = 3456;
+
+  ALOGD("Disabling nonexistent nanoapp");
+  Result result = hubApi->disableNanoApp(getHubId(), kNonExistentAppId,
+                                         cb->expectedTxnId);
+  EXPECT_TRUE(checkFailureSyncOrAsync(result, Result::BAD_PARAMS,
+                                      cb->promise.get_future()));
+}
+
+// Parameterize all SingleContexthubTest tests against each valid hub ID
+INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubHidlTest,
+                        ::testing::ValuesIn(getHubIds()));
+INSTANTIATE_TEST_CASE_P(HubIdSpecificTests, ContexthubTxnTest,
+                        ::testing::ValuesIn(getHubIds()));
+
+} // anonymous namespace
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+
diff --git a/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
new file mode 100644
index 0000000..a46a0e6
--- /dev/null
+++ b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ContexthubHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/contexthub/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..a314d1b
--- /dev/null
+++ b/contexthub/1.0/vts/functional/vts/testcases/hal/contexthub/hidl/target/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<configuration description="Config for VTS Context Hub HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="ContexthubHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/contexthub_hidl_hal_test/contexthub_hidl_hal_test,
+            _64bit::DATA/nativetest64/contexthub_hidl_hal_test/contexthub_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-disable-framework" value="true" />
+        <option name="test-timeout" value="10m" />
+    </test>
+</configuration>
+
diff --git a/contexthub/1.0/vts/types.vts b/contexthub/1.0/vts/types.vts
new file mode 100644
index 0000000..12576b1
--- /dev/null
+++ b/contexthub/1.0/vts/types.vts
@@ -0,0 +1,475 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.contexthub"
+
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::Result"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "UNKNOWN_FAILURE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "BAD_PARAMS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "NOT_INIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "TRANSACTION_FAILED"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "TRANSACTION_PENDING"
+        scalar_value: {
+            uint32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::NanoAppFlags"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SIGNED"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "ENCRYPTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::NanoAppBinary"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "appVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_MASK
+        predefined_type: "::android::hardware::contexthub::V1_0::NanoAppFlags"
+    }
+    struct_value: {
+        name: "targetChreApiMajorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "targetChreApiMinorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "customBinary"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::SensorType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "RESERVED"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "ACCELEROMETER"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "GYROSCOPE"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "MAGNETOMETER"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "BAROMETER"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PROXIMITY_SENSOR"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "AMBIENT_LIGHT_SENSOR"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "STATIONARY_DETECT"
+        scalar_value: {
+            uint32_t: 7
+        }
+        enumerator: "INSTANT_MOTION_DETECT"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "GPS"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "WIFI"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "AUDIO"
+        scalar_value: {
+            uint32_t: 768
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "BLE"
+        scalar_value: {
+            uint32_t: 1280
+        }
+        enumerator: "WWAN"
+        scalar_value: {
+            uint32_t: 1536
+        }
+        enumerator: "PRIVATE_SENSOR_BASE"
+        scalar_value: {
+            uint32_t: 65536
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::PhysicalSensor"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sensorType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::contexthub::V1_0::SensorType"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "vendor"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "version"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "fifoReservedCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "fifoMaxCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "minDelayMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "maxDelayMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "peakPowerMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::ContextHub"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "vendor"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "toolchain"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "platformVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "toolchainVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "hubId"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "peakMips"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "stoppedPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "sleepPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "peakPowerDrawMw"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "connectedSensors"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::PhysicalSensor"
+        }
+    }
+    struct_value: {
+        name: "maxSupportedMsgLen"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "chrePlatformId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "chreApiMajorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "chreApiMinorVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "chrePatchVersion"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HostEndPoint"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint16_t"
+
+        enumerator: "BROADCAST"
+        scalar_value: {
+            uint16_t: 65535
+        }
+        enumerator: "UNSPECIFIED"
+        scalar_value: {
+            uint16_t: 65534
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::ContextHubMsg"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appName"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "hostEndPoint"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "msgType"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "msg"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubMemoryType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "MAIN"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "SECONDARY"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "TCM"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubMemoryFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "READ"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "WRITE"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "EXEC"
+        scalar_value: {
+            uint32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::MemRange"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "totalBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "freeBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::contexthub::V1_0::HubMemoryType"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_MASK
+        predefined_type: "::android::hardware::contexthub::V1_0::HubMemoryFlag"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::AsyncEventType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "RESTARTED"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::TransactionResult"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FAILURE"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::contexthub::V1_0::HubAppInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appId"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "version"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "memUsage"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::contexthub::V1_0::MemRange"
+        }
+    }
+    struct_value: {
+        name: "enabled"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
diff --git a/contexthub/Android.bp b/contexthub/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/contexthub/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
new file mode 100644
index 0000000..d899114
--- /dev/null
+++ b/drm/1.0/Android.bp
@@ -0,0 +1,88 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.drm@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.drm@1.0",
+    srcs: [
+        "types.hal",
+        "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+        "IDrmPluginListener.hal",
+    ],
+    out: [
+        "android/hardware/drm/1.0/types.cpp",
+        "android/hardware/drm/1.0/CryptoFactoryAll.cpp",
+        "android/hardware/drm/1.0/CryptoPluginAll.cpp",
+        "android/hardware/drm/1.0/DrmFactoryAll.cpp",
+        "android/hardware/drm/1.0/DrmPluginAll.cpp",
+        "android/hardware/drm/1.0/DrmPluginListenerAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.drm@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.drm@1.0",
+    srcs: [
+        "types.hal",
+        "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+        "IDrmPluginListener.hal",
+    ],
+    out: [
+        "android/hardware/drm/1.0/types.h",
+        "android/hardware/drm/1.0/ICryptoFactory.h",
+        "android/hardware/drm/1.0/IHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BnHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BpHwCryptoFactory.h",
+        "android/hardware/drm/1.0/BsCryptoFactory.h",
+        "android/hardware/drm/1.0/ICryptoPlugin.h",
+        "android/hardware/drm/1.0/IHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BnHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BpHwCryptoPlugin.h",
+        "android/hardware/drm/1.0/BsCryptoPlugin.h",
+        "android/hardware/drm/1.0/IDrmFactory.h",
+        "android/hardware/drm/1.0/IHwDrmFactory.h",
+        "android/hardware/drm/1.0/BnHwDrmFactory.h",
+        "android/hardware/drm/1.0/BpHwDrmFactory.h",
+        "android/hardware/drm/1.0/BsDrmFactory.h",
+        "android/hardware/drm/1.0/IDrmPlugin.h",
+        "android/hardware/drm/1.0/IHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BnHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BpHwDrmPlugin.h",
+        "android/hardware/drm/1.0/BsDrmPlugin.h",
+        "android/hardware/drm/1.0/IDrmPluginListener.h",
+        "android/hardware/drm/1.0/IHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BnHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BpHwDrmPluginListener.h",
+        "android/hardware/drm/1.0/BsDrmPluginListener.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.drm@1.0",
+    generated_sources: ["android.hardware.drm@1.0_genc++"],
+    generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/drm/1.0/ICryptoFactory.hal b/drm/1.0/ICryptoFactory.hal
new file mode 100644
index 0000000..aeab9bc
--- /dev/null
+++ b/drm/1.0/ICryptoFactory.hal
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.0;
+
+import ICryptoPlugin;
+
+/**
+ * Ref: frameworks/native/include/media/hardware/CryptoAPI.h:CryptoFactory
+ *
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ */
+interface ICryptoFactory {
+    /**
+     * Determine if a crypto scheme is supported by this HAL
+     *
+     * @param uuid identifies the crypto scheme in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
+
+    /**
+     * Create a crypto plugin for the specified uuid and scheme-specific
+     * initialization data.
+     *
+     * @param uuid uniquely identifies the drm scheme. See
+     * http://dashif.org/identifiers/protection for uuid assignments
+     * @param initData scheme-specific init data.
+     * @return status the status of the call. The HAL implementation must return
+     * OK if the plugin is created and ERROR_DRM_CANNOT_HANDLE if the plugin
+     * cannot be created.
+     * @return cryptoPlugin the created ICryptoPlugin
+     */
+    createPlugin(uint8_t[16] uuid, vec<uint8_t> initData)
+        generates (Status status, ICryptoPlugin cryptoPlugin);
+};
diff --git a/drm/1.0/ICryptoPlugin.hal b/drm/1.0/ICryptoPlugin.hal
new file mode 100644
index 0000000..d66151e
--- /dev/null
+++ b/drm/1.0/ICryptoPlugin.hal
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.0;
+
+import android.hardware.drm@1.0::types;
+
+/**
+ * Ref: frameworks/native/include/media/hardware/CryptoAPI.h:CryptoPlugin
+ *
+ * ICryptoPlugin is the HAL for vendor-provided crypto plugins.
+ * It allows crypto sessions to be opened and operated on, to
+ * load crypto keys for a codec to decrypt protected video content.
+ */
+interface ICryptoPlugin {
+    /**
+     * Check if the specified mime-type requires a secure decoder
+     * component.
+     *
+     * @param mime The content mime-type
+     * @return secureRequired must be true only if a secure decoder is required
+     * for the specified mime-type
+     */
+    requiresSecureDecoderComponent(string mime)
+        generates(bool secureRequired);
+
+    /**
+     * Notify a plugin of the currently configured resolution
+     *
+     * @param width - the display resolutions's width
+     * @param height - the display resolution's height
+     */
+    notifyResolution(uint32_t width, uint32_t height);
+
+    /**
+     * Associate a mediadrm session with this crypto session
+     *
+     * @param sessionId the MediaDrm session ID to associate with this crypto
+     * session
+     * @return status the status of the call, status must be
+     * ERROR_DRM_SESSION_NOT_OPENED if the session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE if the operation is not supported by the drm
+     * scheme.
+     */
+    setMediaDrmSession(vec<uint8_t> sessionId) generates(Status status);
+
+    /**
+     * Set a shared memory base for subsequent decrypt operations. The buffer
+     * base is a hidl_memory which maps shared memory in the HAL module.
+     * After the shared buffer base is established, the decrypt() method
+     * receives SharedBuffer instances which specify the buffer address range
+     * for decrypt source and destination addresses.
+     */
+    setSharedBufferBase(memory base);
+
+    /**
+     * Decrypt an array of subsamples from the source memory buffer to the
+     * destination memory buffer.
+     *
+     * @param secure a flag to indicate if a secure decoder is being used. This
+     * enables the plugin to configure buffer modes to work consistently with
+     * a secure decoder.
+     * @param the keyId for the key that should be used to do the
+     * the decryption. The keyId refers to a key in the associated
+     * MediaDrm instance.
+     * @param iv the initialization vector to use
+     * @param mode the crypto mode to use
+     * @param pattern the crypto pattern to use
+     * @param subSamples a vector of subsamples indicating the number
+     * of clear and encrypted bytes to process. This allows the decrypt
+     * call to operate on a range of subsamples in a single call
+     * @param source the input buffer for the decryption
+     * @param offset the offset of the first byte of encrypted data from
+     * the base of the source buffer
+     * @param destination the output buffer for the decryption
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_NO_LICENSE if no license keys have been
+     * loaded, ERROR_DRM_LICENSE_EXPIRED if the license keys have expired,
+     * ERROR_DRM_RESOURCE_BUSY if the resources required to perform the
+     * decryption are not available, ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+     * if required output protections are not active,
+     * ERROR_DRM_SESSION_NOT_OPENED if the decrypt session is not opened, or
+     * ERROR_DRM_CANNOT_HANDLE in other failure cases.
+     * @return bytesWritten the number of bytes output from the decryption
+     * @return detailedError if the error is a vendor-specific error, the
+     * vendor's crypto HAL may provide a detailed error string to help
+     * describe the error.
+     */
+    decrypt(bool secure, uint8_t[16] keyId, uint8_t[16] iv, Mode mode,
+        Pattern pattern, vec<SubSample> subSamples,
+            SharedBuffer source, uint64_t offset, DestinationBuffer destination)
+        generates(Status status, uint32_t bytesWritten, string detailedError);
+};
diff --git a/drm/1.0/IDrmFactory.hal b/drm/1.0/IDrmFactory.hal
new file mode 100644
index 0000000..de53929
--- /dev/null
+++ b/drm/1.0/IDrmFactory.hal
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package android.hardware.drm@1.0;
+
+import IDrmPlugin;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmFactory
+ *
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt* protected video content.
+ */
+
+interface IDrmFactory {
+    /**
+     * Determine if a crypto scheme is supported by this HAL
+     *
+     * @param uuid identifies the crypto scheme in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isCryptoSchemeSupported(uint8_t[16] uuid) generates(bool isSupported);
+
+    /**
+     * Determine if the HAL factory is able to construct plugins that support a
+     * given media container format specified by mimeType
+     *
+     * @param mimeType identifies the mime type in question
+     * @return isSupported must be true only if the scheme is supported
+     */
+    isContentTypeSupported(string mimeType) generates(bool isSupported);
+
+    /**
+     * Create a drm plugin instance for the specified uuid and scheme-specific
+     * initialization data.
+     *
+     * @param uuid uniquely identifies the drm scheme. See
+     * http://dashif.org/identifiers/protection for uuid assignments
+     * @return status the status of the call. The HAL implementation must return
+     * OK if the plugin is created and ERROR_DRM_CANNOT_HANDLE if the plugin
+     * cannot be created.
+     */
+    createPlugin(uint8_t[16] uuid) generates (Status status,
+            IDrmPlugin drmPlugin);
+};
diff --git a/drm/1.0/IDrmPlugin.hal b/drm/1.0/IDrmPlugin.hal
new file mode 100644
index 0000000..5bae22d
--- /dev/null
+++ b/drm/1.0/IDrmPlugin.hal
@@ -0,0 +1,542 @@
+/**
+ * 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.
+ */
+package android.hardware.drm@1.0;
+
+import IDrmPluginListener;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmPlugin
+ *
+ * IDrmPlugin is used to interact with a specific drm plugin that was
+ * created by IDrm::createPlugin. A drm plugin provides methods for
+ * obtaining drm keys that may be used by a codec to decrypt protected
+ * video content.
+ */
+interface IDrmPlugin {
+
+    /**
+     * Open a new session with the DrmPlugin object. A session ID is returned
+     * in the sessionId parameter.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_NOT_PROVISIONED if the device requires
+     * provisioning before it can open a session, ERROR_DRM_RESOURCE_BUSY if
+     * there are insufficent resources available to open a session,
+     * ERROR_DRM_CANNOT_HANDLE, if openSession is not supported at the time of
+     * the call or ERROR_DRM_INVALID_STATE if the HAL is in a state where a
+     * session cannot be opened.
+     * @return sessionId the session ID for the newly opened session
+     */
+    openSession() generates (Status status, SessionId sessionId);
+
+    /**
+     * Close a session on the DrmPlugin object
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the session cannot be closed.
+     */
+    closeSession(SessionId sessionId) generates (Status status);
+
+    /**
+     * A key request/response exchange occurs between the app and a License
+     * Server to obtain the keys required to decrypt the content.
+     * getKeyRequest() is used to obtain an opaque key request blob that is
+     * delivered to the license server.
+     *
+     * @param scope may be a sessionId or a keySetId, depending on the
+     * specified keyType. When the keyType is OFFLINE or STREAMING,
+     * scope should be set to the sessionId the keys will be provided to.
+     * When the keyType is RELEASE, scope should be set to the keySetId
+     * of the keys being released.
+     * @param initData container-specific data, its meaning is interpreted
+     * based on the mime type provided in the mimeType parameter. It could
+     * contain, for example, the content ID, key ID or other data obtained
+     * from the content metadata that is required to generate the key request.
+     * initData may be empty when keyType is RELEASE.
+     * @param mimeType identifies the mime type of the content
+     * @param keyType specifies if the keys are to be used for streaming,
+     * offline or a release
+     * @param optionalParameters included in the key request message to
+     * allow a client application to provide additional message parameters to
+     * the server.
+     *
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+     * before it can generate a key request, ERROR_DRM_CANNOT_HANDLE if
+     * getKeyRequest is not supported at the time of the call, BAD_VALUE if any
+     * parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL is in a state
+     * where a key request cannot be generated.
+     * @return request if successful, the opaque key request blob is returned
+     * @return requestType indicates type information about the returned
+     * request. The type may be one of INITIAL, RENEWAL or RELEASE. An
+     * INITIAL request is the first key request for a license. RENEWAL is a
+     * subsequent key request used to refresh the keys in a license. RELEASE
+     * corresponds to a keyType of RELEASE, which indicates keys are being
+     * released.
+     * @return defaultUrl the URL that the request may be sent to, if
+     * provided by the drm HAL. The app may choose to override this
+     * URL.
+     */
+    getKeyRequest(vec<uint8_t> scope, vec<uint8_t> initData,
+            string mimeType, KeyType keyType, KeyedVector optionalParameters)
+        generates (Status status, vec<uint8_t> request,
+                KeyRequestType requestType, string defaultUrl);
+
+    /**
+     * After a key response is received by the app, it is provided to the
+     * Drm plugin using provideKeyResponse.
+     *
+     * @param scope may be a sessionId or a keySetId depending on the type
+     * of the response. Scope should be set to the sessionId when the response
+     * is for either streaming or offline key requests. Scope should be set to
+     * the keySetId when the response is for a release request.
+     * @param response the response from the key server that is being
+     * provided to the drm HAL.
+     *
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, ERROR_DRM_NOT_PROVISIONED if the device requires provisioning
+     * before it can handle the key response, ERROR_DRM_DEVICE_REVOKED if the
+     * device has been disabled by the license policy, ERROR_DRM_CANNOT_HANDLE
+     * if provideKeyResponse is not supported at the time of the call, BAD_VALUE
+     * if any parameters are invalid or ERROR_DRM_INVALID_STATE if the HAL is
+     * in a state where a key response cannot be handled.
+     * @return keySetId when the response is for an offline key request, a
+     * keySetId is returned in the keySetId vector parameter that can be used
+     * to later restore the keys to a new session with the method restoreKeys.
+     * When the response is for a streaming or release request, no keySetId is
+     * returned.
+     */
+    provideKeyResponse(vec<uint8_t> scope, vec<uint8_t> response)
+        generates (Status status, vec<uint8_t> keySetId);
+
+    /**
+     * Remove the current keys from a session
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call.  The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the keys cannot be removed.
+     */
+    removeKeys(SessionId sessionId) generates (Status status);
+
+    /**
+     * Restore persisted offline keys into a new session
+     *
+     * @param sessionId the session id the call applies to
+     * @param keySetId identifies the keys to load, obtained from a prior
+     * call to provideKeyResponse().
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where keys cannot be restored.
+     */
+    restoreKeys(SessionId sessionId,
+            vec<uint8_t> keySetId) generates (Status status);
+
+    /**
+     * Request an informative description of the license for the session. The
+     * status is in the form of {name, value} pairs. Since DRM license policies
+     * vary by vendor, the specific status field names are determined by each
+     * DRM vendor. Refer to your DRM provider documentation for definitions of
+     * the field names for a particular drm scheme.
+     *
+     * @param sessionId the session id the call applies to
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if the sessionId is invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where key status cannot be queried.
+     * @return infoList a list of name value pairs describing the license
+     */
+    queryKeyStatus(SessionId sessionId)
+        generates (Status status, KeyedVector infoList);
+
+    /**
+     * A provision request/response exchange occurs between the app and a
+     * provisioning server to retrieve a device certificate. getProvisionRequest
+     * is used to obtain an opaque provisioning request blob that is delivered
+     * to the provisioning server.
+     *
+     * @param certificateType the type of certificate requested, e.g. "X.509"
+     * @param certificateAuthority identifies the certificate authority. A
+     * certificate authority (CA) is an entity which issues digital certificates
+     * for use by other parties. It is an example of a trusted third party.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the sessionId is invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
+     * request cannot be generated.
+     * @return request if successful the opaque certificate request blob
+     * is returned
+     * @return defaultUrl URL that the provisioning request should be
+     * sent to, if known by the HAL implementation.  If the HAL implementation
+     * does not provide a defaultUrl, the returned string must be empty.
+     */
+    getProvisionRequest(string certificateType, string certificateAuthority)
+        generates (Status status, vec<uint8_t> request, string defaultUrl);
+
+    /**
+     * After a provision response is received by the app from a provisioning
+     * server, it is provided to the Drm HAL using provideProvisionResponse.
+     * The HAL implementation must receive the provision request and
+     * store the provisioned credentials.
+     *
+     * @param response the opaque provisioning response received by the
+     * app from a provisioning server.
+
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_DEVICE_REVOKED if the device has been
+     * disabled by the license policy, BAD_VALUE if any parameters are invalid
+     * or ERROR_DRM_INVALID_STATE if the HAL is in a state where the provision
+     * response cannot be handled.
+     * @return certificate the public certificate resulting from the provisioning
+     * operation, if any. An empty vector indicates that no certificate was
+     * returned.
+     * @return wrappedKey an opaque object containing encrypted private key
+     * material to be used by signRSA when computing an RSA signature on a
+     * message, see the signRSA method.
+     */
+    provideProvisionResponse(vec<uint8_t> response) generates (Status status,
+            vec<uint8_t> certificate, vec<uint8_t> wrappedKey);
+
+    /**
+     * SecureStop is a way of enforcing the concurrent stream limit per
+     * subscriber. It can securely monitor the lifetime of sessions across
+     * device reboots by periodically persisting the session lifetime
+     * status in secure storage.
+     *
+     * A signed version of the sessionID is written to persistent storage on the
+     * device when each MediaCrypto object is created and periodically during
+     * playback. The sessionID is signed by the device private key to prevent
+     * tampering.
+     *
+     * When playback is completed the session is destroyed, and the secure
+     * stops are queried by the app. The app then delivers the secure stop
+     * message to a server which verifies the signature to confirm that the
+     * session and its keys have been removed from the device. The persisted
+     * record on the device is removed after receiving and verifying the
+     * signed response from the server.
+     */
+
+    /**
+     * Get 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 stops
+     * cannot be returned.
+     * @return secureStops a list of the secure stop opaque objects
+     */
+    getSecureStops() generates
+        (Status status, vec<SecureStop> secureStops);
+
+    /**
+     * Get all secure stops by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to return. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @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 returned.
+     * @return secureStop the secure stop opaque object
+     */
+
+    getSecureStop(SecureStopId secureStopId)
+        generates (Status status, SecureStop secureStop);
+
+    /**
+     * Release 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
+     * stops cannot be released.
+     */
+    releaseAllSecureStops() generates (Status status);
+
+    /**
+     * Release a secure stop by secure stop ID
+     *
+     * @param secureStopId the ID of the secure stop to release. The
+     * secure stop ID is delivered by the key server as part of the key
+     * response and must also be known by the app.
+     *
+     * @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.
+     */
+    releaseSecureStop(vec<uint8_t> secureStopId) generates (Status status);
+
+    /**
+     * A drm scheme can have properties that are settable and readable
+     * by an app. There are a few forms of property access methods,
+     * depending on the data type of the property.
+     *
+     * Property values defined by the public API are:
+     *   "vendor" [string] identifies the maker of the drm scheme
+     *   "version" [string] identifies the version of the drm scheme
+     *   "description" [string] describes the drm scheme
+     *   'deviceUniqueId' [byte array] The device unique identifier is
+     *   established during device provisioning and provides a means of
+     *   uniquely identifying each device.
+     *
+     * Since drm scheme properties may vary, additional field names may be
+     * defined by each DRM vendor. Refer to your DRM provider documentation
+     * for definitions of its additional field names.
+     */
+
+    /**
+     * Read a string property value given the property name.
+     *
+     * @param propertyName the name of the property
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be obtained.
+     * @return value the property value string
+     */
+    getPropertyString(string propertyName)
+        generates (Status status, string value);
+
+    /**
+     * Read a byte array property value given the property name.
+     *
+     * @param propertyName the name of the property
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be obtained.
+     * @return value the property value byte array
+     */
+    getPropertyByteArray(string propertyName)
+        generates (Status status, vec<uint8_t> value);
+
+    /**
+     * Write a property string value given the property name
+     *
+     * @param propertyName the name of the property
+     * @param value the value to write
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be set.
+     */
+    setPropertyString(string propertyName, string value)
+        generates (Status status);
+
+    /**
+     * Write a property byte array value given the property name
+     *
+     * @param propertyName the name of the property
+     * @param value the value to write
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: BAD_VALUE if the property name is invalid,
+     * ERROR_DRM_CANNOT_HANDLE if the property is not supported, or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the property
+     * cannot be set.
+     */
+    setPropertyByteArray(string propertyName, vec<uint8_t> value )
+        generates (Status status);
+
+    /**
+     * The following methods implement operations on a CryptoSession to support
+     * encrypt, decrypt, sign verify operations on operator-provided
+     * session keys.
+     */
+
+    /**
+     * Set the cipher algorithm to be used for the specified session.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the algorithm to use. The string conforms to JCA
+     * Standard Names for Cipher Transforms and is case insensitive. An
+     * example algorithm is "AES/CBC/PKCS5Padding".
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
+     */
+    setCipherAlgorithm(SessionId sessionId, string algorithm)
+        generates (Status status);
+
+    /**
+     * Set the MAC algorithm to be used for computing hashes in a session.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the algorithm to use. The string conforms to JCA
+     * Standard Names for Mac Algorithms and is case insensitive. An example MAC
+     * algorithm string is "HmacSHA256".
+     * @return status the status of the call. The status must be OK or one of the
+     * following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the algorithm cannot be set.
+     */
+    setMacAlgorithm(SessionId sessionId, string algorithm)
+        generates (Status status);
+
+    /**
+     * Encrypt the provided input buffer with the cipher algorithm specified by
+     * setCipherAlgorithm and the key selected by keyId, and return the
+     * encrypted data.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for encryption
+     * @param input the input data to encrypt
+     * @param iv the initialization vector to use for encryption
+     * @return status the status of the call. The status must be OK or one of the
+     * following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not opened,
+     * BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the encrypt operation cannot be performed.
+     * @return output the decrypted data
+     */
+    encrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
+
+    /**
+     * Decrypt the provided input buffer with the cipher algorithm
+     * specified by setCipherAlgorithm and the key selected by keyId,
+     * and return the decrypted data.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param input the input data to decrypt
+     * @param iv the initialization vector to use for decryption
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the decrypt operation cannot be
+     * performed.
+     * @return output the decrypted data
+     */
+    decrypt(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> input,
+            vec<uint8_t> iv) generates (Status status, vec<uint8_t> output);
+
+    /**
+     * Compute a signature over the provided message using the mac algorithm
+     * specified by setMacAlgorithm and the key selected by keyId and return
+     * the signature.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param message the message to compute a signature over
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the sign operation cannot be
+     * performed.
+     * @return signature the computed signature
+     */
+    sign(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message)
+        generates (Status status, vec<uint8_t> signature);
+
+    /**
+     * Compute a hash of the provided message using the mac algorithm specified
+     * by setMacAlgorithm and the key selected by keyId, and compare with the
+     * expected result.
+     *
+     * @param sessionId the session id the call applies to
+     * @param keyId the ID of the key to use for decryption
+     * @param message the message to compute a hash of
+     * @param signature the signature to verify
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is not
+     * opened, BAD_VALUE if any parameters are invalid or ERROR_DRM_INVALID_STATE
+     * if the HAL is in a state where the verify operation cannot be
+     * performed.
+     * @return match true if the signature is verified positively,
+     * false otherwise.
+     */
+    verify(SessionId sessionId, vec<uint8_t> keyId, vec<uint8_t> message,
+            vec<uint8_t> signature) generates (Status status, bool match);
+
+    /**
+     * Compute an RSA signature on the provided message using the specified
+     * algorithm.
+     *
+     * @param sessionId the session id the call applies to
+     * @param algorithm the signing algorithm, such as "RSASSA-PSS-SHA1"
+     * or "PKCS1-BlockType1"
+     * @param message the message to compute the signature on
+     * @param wrappedKey the private key returned during provisioning as
+     * returned by provideProvisionResponse.
+     * @return status the status of the call. The status must be OK or one of
+     * the following errors: ERROR_DRM_SESSION_NOT_OPENED if the session is
+     * not opened, BAD_VALUE if any parameters are invalid or
+     * ERROR_DRM_INVALID_STATE if the HAL is in a state where the signRSA
+     * operation cannot be performed.
+     * @return signature the RSA signature computed over the message
+     */
+    signRSA(SessionId sessionId, string algorithm, vec<uint8_t> message,
+        vec<uint8_t> wrappedkey)
+        generates (Status status, vec<uint8_t> signature);
+
+    /**
+     * Plugins call the following methods to deliver events to the
+     * java app.
+     */
+
+    /**
+     * Set a listener for a drm session. This allows the drm HAL to
+     * make asynchronous calls back to the client of IDrm.
+     *
+     * @param listener instance of IDrmPluginListener to receive the events
+     */
+    setListener(IDrmPluginListener listener);
+
+    /**
+     * Legacy event sending method, it sends events of various types using a
+     * single overloaded set of parameters. This form is deprecated.
+     *
+     * @param eventType the type of the event
+     * @param sessionId identifies the session the event originated from
+     * @param data event-specific data blob
+     */
+    sendEvent(EventType eventType, SessionId sessionId, vec<uint8_t> data);
+
+    /**
+     * Send a license expiration update to the listener. The expiration
+     * update indicates how long the current license is valid before it
+     * needs to be renewed.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param expiryTimeInMS the time when the keys need to be renewed.
+     * The time is in milliseconds, relative to the Unix epoch. A time of 0
+     * indicates that the keys never expire.
+     */
+     sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+
+    /**
+     * Send a keys change event to the listener. The keys change event
+     * indicates the status of each key in the session. Keys can be
+     * indicated as being usable, expired, outputnotallowed or statuspending.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param keyStatusList indicates the status for each key ID in the
+     * session.
+     * @param hasNewUsableKey indicates if the event includes at least one
+     * key that has become usable.
+     */
+    sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+            bool hasNewUsableKey);
+};
diff --git a/drm/1.0/IDrmPluginListener.hal b/drm/1.0/IDrmPluginListener.hal
new file mode 100644
index 0000000..15ce008
--- /dev/null
+++ b/drm/1.0/IDrmPluginListener.hal
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package android.hardware.drm@1.0;
+
+import android.hardware.drm@1.0::types;
+
+/**
+ * Ref: frameworks/native/include/media/drm/DrmAPI.h:DrmPluginListener
+ */
+
+/**
+ * IDrmPluginListener is a listener interface for Drm events sent from an
+ * IDrmPlugin instance.
+ */
+interface IDrmPluginListener {
+
+    /**
+     * Legacy event sending method, it sends events of various types using a
+     * single overloaded set of parameters. This form is deprecated.
+     *
+     * @param eventType the type of the event
+     * @param sessionId identifies the session the event originated from
+     * @param data event-specific data blob
+     */
+    oneway sendEvent(EventType eventType, SessionId sessionId,
+            vec<uint8_t> data);
+
+    /**
+     * Send a license expiration update to the listener. The expiration
+     * update indicates how long the current keys are valid before they
+     * need to be renewed.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param expiryTimeInMS the time when the keys need to be renewed.
+     * The time is in milliseconds, relative to the Unix epoch. A time
+     * of 0 indicates that the keys never expire.
+     */
+    oneway sendExpirationUpdate(SessionId sessionId, int64_t expiryTimeInMS);
+
+    /**
+     * Send a keys change event to the listener. The keys change event
+     * indicates the status of each key in the session. Keys can be
+     * indicated as being usable, expired, outputnotallowed or statuspending.
+     *
+     * @param sessionId identifies the session the event originated from
+     * @param keyStatusList indicates the status for each key ID in the
+     * session.
+     * @param hasNewUsableKey indicates if the event includes at least one
+     * key that has become usable.
+     */
+    oneway sendKeysChange(SessionId sessionId, vec<KeyStatus> keyStatusList,
+            bool hasNewUsableKey);
+};
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
new file mode 100644
index 0000000..ac5b90a
--- /dev/null
+++ b/drm/1.0/default/Android.mk
@@ -0,0 +1,79 @@
+#
+# 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.
+
+
+############# Build legacy drm service ############
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm@1.0-service
+LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+  service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+  android.hardware.drm@1.0 \
+  android.hidl.memory@1.0 \
+  libhidlbase \
+  libhidltransport \
+  libhardware \
+  libhwbinder \
+  liblog \
+  libutils \
+
+LOCAL_C_INCLUDES := \
+  hardware/interfaces/drm
+
+# TODO: The legacy DRM plugins only support 32-bit. They need
+# to be migrated to 64-bit (b/18948909)
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_EXECUTABLE)
+
+############# Build legacy drm impl library ############
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.drm@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    DrmFactory.cpp \
+    DrmPlugin.cpp \
+    CryptoFactory.cpp \
+    CryptoPlugin.cpp \
+    TypeConvert.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.drm@1.0 \
+    android.hidl.memory@1.0 \
+    libhidlbase \
+    libhidlmemory \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libmediadrm \
+    libstagefright_foundation \
+    libutils \
+
+LOCAL_C_INCLUDES := \
+    frameworks/native/include \
+    frameworks/av/include
+
+# TODO: The legacy DRM plugins only support 32-bit. They need
+# to be migrated to 64-bit (b/18948909)
+LOCAL_32_BIT_ONLY := true
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/CryptoFactory.cpp b/drm/1.0/default/CryptoFactory.cpp
new file mode 100644
index 0000000..e46233d
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
+
+#include "CryptoFactory.h"
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    CryptoFactory::CryptoFactory() :
+        loader("/vendor/lib/mediadrm", "createCryptoFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+    Return<bool> CryptoFactory::isCryptoSchemeSupported(
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> CryptoFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::CryptoPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createPlugin(uuid.data(),
+                        initData.data(), initData.size(), &legacyPlugin);
+                CryptoPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Crypto legacy HAL: failed to create crypto plugin");
+                } else {
+                    newPlugin = new CryptoPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* /* name */) {
+        return new CryptoFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoFactory.h b/drm/1.0/default/CryptoFactory.h
new file mode 100644
index 0000000..412b557
--- /dev/null
+++ b/drm/1.0/default/CryptoFactory.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
+
+#include <android/hardware/drm/1.0/ICryptoFactory.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::ICryptoFactory;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct CryptoFactory : public ICryptoFactory {
+    CryptoFactory();
+    virtual ~CryptoFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            const hidl_vec<uint8_t>& initData, createPlugin_cb _hidl_cb)
+            override;
+
+private:
+    android::PluginLoader<android::CryptoFactory> loader;
+
+    CryptoFactory(const CryptoFactory &) = delete;
+    void operator=(const CryptoFactory &) = delete;
+};
+
+extern "C" ICryptoFactory* HIDL_FETCH_ICryptoFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOFACTORY_H
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
new file mode 100644
index 0000000..1a32706
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
+
+#include "CryptoPlugin.h"
+#include "TypeConvert.h"
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+#include <media/stagefright/foundation/AString.h>
+#include <utils/Log.h>
+
+using android::hardware::hidl_memory;
+using android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin follow
+    Return<bool> CryptoPlugin::requiresSecureDecoderComponent(
+            const hidl_string& mime) {
+        return mLegacyPlugin->requiresSecureDecoderComponent(mime);
+    }
+
+    Return<void> CryptoPlugin::notifyResolution(uint32_t width,
+            uint32_t height) {
+        mLegacyPlugin->notifyResolution(width, height);
+        return Void();
+    }
+
+    Return<Status> CryptoPlugin::setMediaDrmSession(
+            const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->setMediaDrmSession(toVector(sessionId)));
+    }
+
+    Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base) {
+        mSharedBufferBase = mapMemory(base);
+        return Void();
+    }
+
+    Return<void> CryptoPlugin::decrypt(bool secure,
+            const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode,
+            const Pattern& pattern, const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& source, uint64_t offset,
+            const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) {
+
+        android::CryptoPlugin::Mode legacyMode;
+        switch(mode) {
+        case Mode::UNENCRYPTED:
+            legacyMode = android::CryptoPlugin::kMode_Unencrypted;
+            break;
+        case Mode::AES_CTR:
+            legacyMode = android::CryptoPlugin::kMode_AES_CTR;
+            break;
+        case Mode::AES_CBC_CTS:
+            legacyMode = android::CryptoPlugin::kMode_AES_WV;
+            break;
+        case Mode::AES_CBC:
+            legacyMode = android::CryptoPlugin::kMode_AES_CBC;
+            break;
+        }
+        android::CryptoPlugin::Pattern legacyPattern;
+        legacyPattern.mEncryptBlocks = pattern.encryptBlocks;
+        legacyPattern.mSkipBlocks = pattern.skipBlocks;
+
+        android::CryptoPlugin::SubSample *legacySubSamples =
+            new android::CryptoPlugin::SubSample[subSamples.size()];
+
+        for (size_t i = 0; i < subSamples.size(); i++) {
+            legacySubSamples[i].mNumBytesOfClearData
+                = subSamples[i].numBytesOfClearData;
+            legacySubSamples[i].mNumBytesOfEncryptedData
+                = subSamples[i].numBytesOfEncryptedData;
+        }
+
+        AString detailMessage;
+
+        if (source.offset + offset + source.size > mSharedBufferBase->getSize()) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+            return Void();
+        }
+
+        uint8_t *base = static_cast<uint8_t *>
+                (static_cast<void *>(mSharedBufferBase->getPointer()));
+        void *srcPtr = static_cast<void *>(base + source.offset + offset);
+
+        void *destPtr = NULL;
+        if (destination.type == BufferType::SHARED_MEMORY) {
+            const SharedBuffer& destBuffer = destination.nonsecureMemory;
+            if (destBuffer.offset + destBuffer.size > mSharedBufferBase->getSize()) {
+                _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
+                return Void();
+            }
+            destPtr = static_cast<void *>(base + destination.nonsecureMemory.offset);
+        } else if (destination.type == BufferType::NATIVE_HANDLE) {
+            native_handle_t *handle = const_cast<native_handle_t *>(
+                    destination.secureMemory.getNativeHandle());
+            destPtr = static_cast<void *>(handle);
+        }
+        ssize_t result = mLegacyPlugin->decrypt(secure, keyId.data(), iv.data(),
+                legacyMode, legacyPattern, srcPtr, legacySubSamples,
+                subSamples.size(), destPtr, &detailMessage);
+
+        delete[] legacySubSamples;
+
+        uint32_t status;
+        uint32_t bytesWritten;
+
+        if (result >= 0) {
+            status = android::OK;
+            bytesWritten = result;
+        } else {
+            status = -result;
+            bytesWritten = 0;
+        }
+
+        _hidl_cb(toStatus(status), bytesWritten, detailMessage.c_str());
+        return Void();
+    }
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/CryptoPlugin.h b/drm/1.0/default/CryptoPlugin.h
new file mode 100644
index 0000000..f805f09
--- /dev/null
+++ b/drm/1.0/default/CryptoPlugin.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
+
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <android/hardware/drm/1.0/ICryptoPlugin.h>
+#include <hidl/Status.h>
+#include <media/hardware/CryptoAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::DestinationBuffer;
+using ::android::hardware::drm::V1_0::ICryptoPlugin;
+using ::android::hardware::drm::V1_0::Mode;
+using ::android::hardware::drm::V1_0::Pattern;
+using ::android::hardware::drm::V1_0::SubSample;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+struct CryptoPlugin : public ICryptoPlugin {
+    CryptoPlugin(android::CryptoPlugin *plugin) : mLegacyPlugin(plugin) {}
+
+    ~CryptoPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::ICryptoPlugin
+    // follow.
+
+    Return<bool> requiresSecureDecoderComponent(const hidl_string& mime)
+            override;
+
+    Return<void> notifyResolution(uint32_t width, uint32_t height) override;
+
+    Return<Status> setMediaDrmSession(const hidl_vec<uint8_t>& sessionId)
+            override;
+
+    Return<void> setSharedBufferBase(const ::android::hardware::hidl_memory& base)
+            override;
+
+    Return<void> decrypt(bool secure, const hidl_array<uint8_t, 16>& keyId,
+            const hidl_array<uint8_t, 16>& iv, Mode mode, const Pattern& pattern,
+            const hidl_vec<SubSample>& subSamples, const SharedBuffer& source,
+            uint64_t offset, const DestinationBuffer& destination,
+            decrypt_cb _hidl_cb) override;
+
+private:
+    android::CryptoPlugin *mLegacyPlugin;
+    sp<IMemory> mSharedBufferBase;
+
+    CryptoPlugin() = delete;
+    CryptoPlugin(const CryptoPlugin &) = delete;
+    void operator=(const CryptoPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__CRYPTOPLUGIN_H
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
new file mode 100644
index 0000000..b6f642f
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
+
+#include "DrmFactory.h"
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    DrmFactory::DrmFactory() :
+        loader("/vendor/lib/mediadrm", "createDrmFactory") {
+    }
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+    Return<bool> DrmFactory::isCryptoSchemeSupported (
+            const hidl_array<uint8_t, 16>& uuid) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<bool> DrmFactory::isContentTypeSupported (
+            const hidl_string& mimeType) {
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isContentTypeSupported(String8(mimeType.c_str()))) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    Return<void> DrmFactory::createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) {
+
+        for (size_t i = 0; i < loader.factoryCount(); i++) {
+            if (loader.getFactory(i)->isCryptoSchemeSupported(uuid.data())) {
+                android::DrmPlugin *legacyPlugin = NULL;
+                status_t status = loader.getFactory(i)->createDrmPlugin(
+                        uuid.data(), &legacyPlugin);
+                DrmPlugin *newPlugin = NULL;
+                if (legacyPlugin == NULL) {
+                    ALOGE("Drm legacy HAL: failed to create drm plugin");
+                } else {
+                    newPlugin = new DrmPlugin(legacyPlugin);
+                }
+                _hidl_cb(toStatus(status), newPlugin);
+                return Void();
+            }
+        }
+        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, NULL);
+        return Void();
+    }
+
+    IDrmFactory* HIDL_FETCH_IDrmFactory(const char* /* name */) {
+        return new DrmFactory();
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmFactory.h b/drm/1.0/default/DrmFactory.h
new file mode 100644
index 0000000..78b7f6e
--- /dev/null
+++ b/drm/1.0/default/DrmFactory.h
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
+
+#include <android/hardware/drm/1.0/IDrmFactory.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+#include <media/PluginLoader.h>
+#include <media/SharedLibrary.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::IDrmFactory;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmFactory : public IDrmFactory {
+    DrmFactory();
+    virtual ~DrmFactory() {}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmFactory follow.
+
+    Return<bool> isCryptoSchemeSupported(const hidl_array<uint8_t, 16>& uuid)
+            override;
+
+    Return<bool> isContentTypeSupported(const hidl_string &mimeType)
+            override;
+
+    Return<void> createPlugin(const hidl_array<uint8_t, 16>& uuid,
+            createPlugin_cb _hidl_cb) override;
+
+private:
+    android::PluginLoader<android::DrmFactory> loader;
+
+    DrmFactory(const DrmFactory &) = delete;
+    void operator=(const DrmFactory &) = delete;
+};
+
+extern "C" IDrmFactory* HIDL_FETCH_IDrmFactory(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMFACTORY_H
diff --git a/drm/1.0/default/DrmPlugin.cpp b/drm/1.0/default/DrmPlugin.cpp
new file mode 100644
index 0000000..1b2f90e
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.cpp
@@ -0,0 +1,426 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+#include "DrmPlugin.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> DrmPlugin::openSession(openSession_cb _hidl_cb) {
+        Vector<uint8_t> legacySessionId;
+        status_t status = mLegacyPlugin->openSession(legacySessionId);
+        _hidl_cb(toStatus(status), toHidlVec(legacySessionId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::closeSession(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->closeSession(toVector(sessionId)));
+    }
+
+    Return<void> DrmPlugin::getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) {
+
+        status_t status = android::OK;
+
+        android::DrmPlugin::KeyType legacyKeyType;
+        switch(keyType) {
+        case KeyType::OFFLINE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Offline;
+            break;
+        case KeyType::STREAMING:
+            legacyKeyType = android::DrmPlugin::kKeyType_Streaming;
+            break;
+        case KeyType::RELEASE:
+            legacyKeyType = android::DrmPlugin::kKeyType_Release;
+            break;
+        default:
+            status = android::BAD_VALUE;
+            break;
+        }
+
+        Vector<uint8_t> legacyRequest;
+        KeyRequestType requestType = KeyRequestType::UNKNOWN;
+        String8 defaultUrl;
+
+        if (status == android::OK) {
+            android::KeyedVector<String8, String8> legacyOptionalParameters;
+            for (size_t i = 0; i < optionalParameters.size(); i++) {
+                legacyOptionalParameters.add(String8(optionalParameters[i].key),
+                        String8(optionalParameters[i].value));
+            }
+
+            android::DrmPlugin::KeyRequestType legacyRequestType =
+                    android::DrmPlugin::kKeyRequestType_Unknown;
+
+            status_t status = mLegacyPlugin->getKeyRequest(toVector(scope),
+                    toVector(initData), String8(mimeType), legacyKeyType,
+                    legacyOptionalParameters, legacyRequest, defaultUrl,
+                    &legacyRequestType);
+
+            switch(legacyRequestType) {
+            case android::DrmPlugin::kKeyRequestType_Initial:
+                requestType = KeyRequestType::INITIAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Renewal:
+                requestType = KeyRequestType::RENEWAL;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Release:
+                requestType = KeyRequestType::RELEASE;
+                break;
+            case android::DrmPlugin::kKeyRequestType_Unknown:
+                status = android::BAD_VALUE;
+                break;
+            }
+        }
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest), requestType,
+                 defaultUrl.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> keySetId;
+        status_t status = mLegacyPlugin->provideKeyResponse(toVector(scope),
+                toVector(response), keySetId);
+        _hidl_cb(toStatus(status), toHidlVec(keySetId));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::removeKeys(const hidl_vec<uint8_t>& sessionId) {
+        return toStatus(mLegacyPlugin->removeKeys(toVector(sessionId)));
+    }
+
+    Return<Status> DrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) {
+        status_t legacyStatus = mLegacyPlugin->restoreKeys(toVector(sessionId),
+                toVector(keySetId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) {
+
+        android::KeyedVector<String8, String8> legacyInfoMap;
+        status_t status = mLegacyPlugin->queryKeyStatus(toVector(sessionId),
+                legacyInfoMap);
+
+        Vector<KeyValue> infoMapVec;
+        for (size_t i = 0; i < legacyInfoMap.size(); i++) {
+            KeyValue keyValuePair;
+            keyValuePair.key = String8(legacyInfoMap.keyAt(i));
+            keyValuePair.value = String8(legacyInfoMap.valueAt(i));
+            infoMapVec.push_back(keyValuePair);
+        }
+        _hidl_cb(toStatus(status), toHidlVec(infoMapVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getProvisionRequest(
+            const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyRequest;
+        String8 legacyDefaultUrl;
+        status_t status = mLegacyPlugin->getProvisionRequest(
+                String8(certificateType), String8(certificateAuthority),
+                legacyRequest, legacyDefaultUrl);
+
+        _hidl_cb(toStatus(status), toHidlVec(legacyRequest),
+                hidl_string(legacyDefaultUrl));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::provideProvisionResponse(
+            const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) {
+
+        Vector<uint8_t> certificate;
+        Vector<uint8_t> wrappedKey;
+
+        status_t legacyStatus = mLegacyPlugin->provideProvisionResponse(
+                toVector(response), certificate, wrappedKey);
+
+        _hidl_cb(toStatus(legacyStatus), toHidlVec(certificate),
+                toHidlVec(wrappedKey));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStops(getSecureStops_cb _hidl_cb) {
+        List<Vector<uint8_t> > legacySecureStops;
+        status_t status = mLegacyPlugin->getSecureStops(legacySecureStops);
+
+        Vector<SecureStop> secureStopsVec;
+        List<Vector<uint8_t> >::iterator iter = legacySecureStops.begin();
+
+        while (iter != legacySecureStops.end()) {
+            SecureStop secureStop;
+            secureStop.opaqueData = toHidlVec(*iter++);
+            secureStopsVec.push_back(secureStop);
+        }
+
+        _hidl_cb(toStatus(status), toHidlVec(secureStopsVec));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySecureStop;
+        status_t status = mLegacyPlugin->getSecureStop(toVector(secureStopId),
+                legacySecureStop);
+
+        SecureStop secureStop;
+        secureStop.opaqueData = toHidlVec(legacySecureStop);
+        _hidl_cb(toStatus(status), secureStop);
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::releaseAllSecureStops() {
+        return toStatus(mLegacyPlugin->releaseAllSecureStops());
+    }
+
+    Return<Status> DrmPlugin::releaseSecureStop(
+            const hidl_vec<uint8_t>& secureStopId) {
+        status_t legacyStatus =
+            mLegacyPlugin->releaseSecureStops(toVector(secureStopId));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) {
+        String8 legacyValue;
+        status_t status = mLegacyPlugin->getPropertyString(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), legacyValue.string());
+        return Void();
+    }
+
+    Return<void> DrmPlugin::getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) {
+        Vector<uint8_t> legacyValue;
+        status_t status = mLegacyPlugin->getPropertyByteArray(
+                String8(propertyName), legacyValue);
+        _hidl_cb(toStatus(status), toHidlVec(legacyValue));
+        return Void();
+    }
+
+    Return<Status> DrmPlugin::setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyString(String8(propertyName),
+                    String8(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setPropertyByteArray(
+            const hidl_string& propertyName, const hidl_vec<uint8_t>& value) {
+        status_t legacyStatus =
+            mLegacyPlugin->setPropertyByteArray(String8(propertyName),
+                    toVector(value));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setCipherAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setCipherAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<Status> DrmPlugin::setMacAlgorithm(
+            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
+        status_t legacyStatus =
+            mLegacyPlugin->setMacAlgorithm(toVector(sessionId),
+                String8(algorithm));
+        return toStatus(legacyStatus);
+    }
+
+    Return<void> DrmPlugin::encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->encrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) {
+
+        Vector<uint8_t> legacyOutput;
+        status_t status = mLegacyPlugin->decrypt(toVector(sessionId),
+                toVector(keyId), toVector(input), toVector(iv), legacyOutput);
+        _hidl_cb(toStatus(status), toHidlVec(legacyOutput));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) {
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->sign(toVector(sessionId),
+                toVector(keyId), toVector(message), legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) {
+
+        bool match;
+        status_t status = mLegacyPlugin->verify(toVector(sessionId),
+                toVector(keyId), toVector(message), toVector(signature),
+                match);
+        _hidl_cb(toStatus(status), match);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedKey, signRSA_cb _hidl_cb) {
+
+        Vector<uint8_t> legacySignature;
+        status_t status = mLegacyPlugin->signRSA(toVector(sessionId),
+                String8(algorithm), toVector(message), toVector(wrappedKey),
+                legacySignature);
+        _hidl_cb(toStatus(status), toHidlVec(legacySignature));
+        return Void();
+    }
+
+    Return<void> DrmPlugin::setListener(const sp<IDrmPluginListener>& listener) {
+        mListener = listener;
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
+        mListener->sendEvent(eventType, sessionId, data);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendExpirationUpdate(
+            const hidl_vec<uint8_t>& sessionId, int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
+        return Void();
+    }
+
+    Return<void> DrmPlugin::sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
+        mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
+        return Void();
+    }
+
+
+    // Methods from android::DrmPluginListener
+
+    void DrmPlugin::sendEvent(android::DrmPlugin::EventType legacyEventType,
+            int /*unused*/, Vector<uint8_t> const *sessionId,
+            Vector<uint8_t> const *data) {
+
+        EventType eventType;
+        bool sendEvent = true;
+        switch(legacyEventType) {
+        case android::DrmPlugin::kDrmPluginEventProvisionRequired:
+            eventType = EventType::PROVISION_REQUIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyNeeded:
+            eventType = EventType::KEY_NEEDED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventKeyExpired:
+            eventType = EventType::KEY_EXPIRED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventVendorDefined:
+            eventType = EventType::VENDOR_DEFINED;
+            break;
+        case android::DrmPlugin::kDrmPluginEventSessionReclaimed:
+            eventType = EventType::SESSION_RECLAIMED;
+            break;
+        default:
+            sendEvent = false;
+            break;
+        }
+        if (sendEvent) {
+            mListener->sendEvent(eventType, toHidlVec(*sessionId),
+                    toHidlVec(*data));
+        }
+    }
+
+    void DrmPlugin::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS) {
+        mListener->sendExpirationUpdate(toHidlVec(*sessionId), expiryTimeInMS);
+    }
+
+    void DrmPlugin::sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *legacyKeyStatusList,
+            bool hasNewUsableKey) {
+
+        Vector<KeyStatus> keyStatusVec;
+        for (size_t i = 0; i < legacyKeyStatusList->size(); i++) {
+            const android::DrmPlugin::KeyStatus &legacyKeyStatus =
+                legacyKeyStatusList->itemAt(i);
+
+            KeyStatus keyStatus;
+
+            switch(legacyKeyStatus.mType) {
+            case android::DrmPlugin::kKeyStatusType_Usable:
+                keyStatus.type = KeyStatusType::USABLE;
+                break;
+            case android::DrmPlugin::kKeyStatusType_Expired:
+                keyStatus.type = KeyStatusType::EXPIRED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_OutputNotAllowed:
+                keyStatus.type = KeyStatusType::OUTPUTNOTALLOWED;
+                break;
+            case android::DrmPlugin::kKeyStatusType_StatusPending:
+                keyStatus.type = KeyStatusType::STATUSPENDING;
+                break;
+            case android::DrmPlugin::kKeyStatusType_InternalError:
+            default:
+                keyStatus.type = KeyStatusType::INTERNALERROR;
+                break;
+            }
+
+            keyStatus.keyId = toHidlVec(legacyKeyStatus.mKeyId);
+            keyStatusVec.push_back(keyStatus);
+        }
+        mListener->sendKeysChange(toHidlVec(*sessionId),
+                toHidlVec(keyStatusVec), hasNewUsableKey);
+    }
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/DrmPlugin.h b/drm/1.0/default/DrmPlugin.h
new file mode 100644
index 0000000..dce6c0c
--- /dev/null
+++ b/drm/1.0/default/DrmPlugin.h
@@ -0,0 +1,169 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+#define ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
+
+#include <android/hardware/drm/1.0/IDrmPlugin.h>
+#include <android/hardware/drm/1.0/IDrmPluginListener.h>
+#include <hidl/Status.h>
+#include <media/drm/DrmAPI.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::drm::V1_0::EventType;
+using ::android::hardware::drm::V1_0::IDrmPlugin;
+using ::android::hardware::drm::V1_0::IDrmPluginListener;
+using ::android::hardware::drm::V1_0::KeyRequestType;
+using ::android::hardware::drm::V1_0::KeyStatus;
+using ::android::hardware::drm::V1_0::KeyType;
+using ::android::hardware::drm::V1_0::KeyValue;
+using ::android::hardware::drm::V1_0::SecureStop;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DrmPlugin : public IDrmPlugin, android::DrmPluginListener {
+
+    DrmPlugin(android::DrmPlugin *plugin) : mLegacyPlugin(plugin) {}
+    ~DrmPlugin() {delete mLegacyPlugin;}
+
+    // Methods from ::android::hardware::drm::V1_0::IDrmPlugin follow.
+
+    Return<void> openSession(openSession_cb _hidl_cb) override;
+
+    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<void> getKeyRequest(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& initData, const hidl_string& mimeType,
+            KeyType keyType, const hidl_vec<KeyValue>& optionalParameters,
+            getKeyRequest_cb _hidl_cb) override;
+
+    Return<void> provideKeyResponse(const hidl_vec<uint8_t>& scope,
+            const hidl_vec<uint8_t>& response, provideKeyResponse_cb _hidl_cb)
+            override;
+
+    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) override;
+
+    Return<Status> restoreKeys(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keySetId) override;
+
+    Return<void> queryKeyStatus(const hidl_vec<uint8_t>& sessionId,
+            queryKeyStatus_cb _hidl_cb) override;
+
+    Return<void> getProvisionRequest(const hidl_string& certificateType,
+            const hidl_string& certificateAuthority,
+            getProvisionRequest_cb _hidl_cb) override;
+
+    Return<void> provideProvisionResponse(const hidl_vec<uint8_t>& response,
+            provideProvisionResponse_cb _hidl_cb) override;
+
+    Return<void> getSecureStops(getSecureStops_cb _hidl_cb) override;
+
+    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
+            getSecureStop_cb _hidl_cb) override;
+
+    Return<Status> releaseAllSecureStops() override;
+
+    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& secureStopId)
+            override;
+
+    Return<void> getPropertyString(const hidl_string& propertyName,
+            getPropertyString_cb _hidl_cb) override;
+
+    Return<void> getPropertyByteArray(const hidl_string& propertyName,
+            getPropertyByteArray_cb _hidl_cb) override;
+
+    Return<Status> setPropertyString(const hidl_string& propertyName,
+            const hidl_string& value) override;
+
+    Return<Status> setPropertyByteArray(const hidl_string& propertyName,
+            const hidl_vec<uint8_t>& value) override;
+
+    Return<Status> setCipherAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<Status> setMacAlgorithm(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm) override;
+
+    Return<void> encrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, encrypt_cb _hidl_cb) override;
+
+    Return<void> decrypt(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& input,
+            const hidl_vec<uint8_t>& iv, decrypt_cb _hidl_cb) override;
+
+    Return<void> sign(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            sign_cb _hidl_cb) override;
+
+    Return<void> verify(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<uint8_t>& keyId, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& signature, verify_cb _hidl_cb) override;
+
+    Return<void> signRSA(const hidl_vec<uint8_t>& sessionId,
+            const hidl_string& algorithm, const hidl_vec<uint8_t>& message,
+            const hidl_vec<uint8_t>& wrappedkey, signRSA_cb _hidl_cb) override;
+
+    Return<void> setListener(const sp<IDrmPluginListener>& listener) override;
+
+    Return<void> sendEvent(EventType eventType,
+            const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data)
+            override;
+
+    Return<void> sendExpirationUpdate(const hidl_vec<uint8_t>& sessionId,
+            int64_t expiryTimeInMS) override;
+
+    Return<void> sendKeysChange(const hidl_vec<uint8_t>& sessionId,
+            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey)
+            override;
+
+    // Methods from android::DrmPluginListener follow
+
+    virtual void sendEvent(android::DrmPlugin::EventType eventType, int extra,
+            Vector<uint8_t> const *sessionId, Vector<uint8_t> const *data);
+
+    virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+            int64_t expiryTimeInMS);
+
+    virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+            Vector<android::DrmPlugin::KeyStatus> const *keyStatusList,
+            bool hasNewUsableKey);
+
+private:
+    android::DrmPlugin *mLegacyPlugin;
+    sp<IDrmPluginListener> mListener;
+
+    DrmPlugin() = delete;
+    DrmPlugin(const DrmPlugin &) = delete;
+    void operator=(const DrmPlugin &) = delete;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DRM_V1_0__DRMPLUGIN_H
diff --git a/drm/1.0/default/TypeConvert.cpp b/drm/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..ede2a38
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.drm@1.0-impl"
+
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::OK:
+        status = Status::OK;
+        break;
+    case android::ERROR_DRM_NO_LICENSE:
+        status = Status::ERROR_DRM_NO_LICENSE;
+        break;
+    case android::ERROR_DRM_LICENSE_EXPIRED:
+        status = Status::ERROR_DRM_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_DRM_SESSION_NOT_OPENED:
+        status = Status::ERROR_DRM_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_DRM_CANNOT_HANDLE:
+        status = Status::ERROR_DRM_CANNOT_HANDLE;
+        break;
+    case android::ERROR_DRM_TAMPER_DETECTED:
+        status = Status::ERROR_DRM_INVALID_STATE;
+        break;
+    case android::BAD_VALUE:
+        status = Status::BAD_VALUE;
+        break;
+    case android::ERROR_DRM_NOT_PROVISIONED:
+        status = Status::ERROR_DRM_NOT_PROVISIONED;
+        break;
+    case android::ERROR_DRM_RESOURCE_BUSY:
+        status = Status::ERROR_DRM_RESOURCE_BUSY;
+        break;
+    case android::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case android::ERROR_DRM_DEVICE_REVOKED:
+        status = Status::ERROR_DRM_DEVICE_REVOKED;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+            legacyStatus);
+        status = Status::ERROR_DRM_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
diff --git a/drm/1.0/default/TypeConvert.h b/drm/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..107fda5
--- /dev/null
+++ b/drm/1.0/default/TypeConvert.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+#define ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
+
+#include <android/hardware/drm/1.0/types.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Vector.h>
+
+namespace android {
+namespace hardware {
+namespace drm {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_vec;
+
+template<typename T> const hidl_vec<T> toHidlVec(const Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(const_cast<T *>(Vector.array()), Vector.size());
+    return vec;
+}
+
+template<typename T> hidl_vec<T> toHidlVec(Vector<T> &Vector) {
+    hidl_vec<T> vec;
+    vec.setToExternal(Vector.editArray(), Vector.size());
+    return vec;
+}
+
+template<typename T> const Vector<T> toVector(const hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return *const_cast<const Vector<T> *>(&vector);
+}
+
+template<typename T> Vector<T> toVector(hidl_vec<T> &vec) {
+    Vector<T> vector;
+    vector.appendArray(vec.data(), vec.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> const Vector<T> toVector(
+        const hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+template<typename T, size_t SIZE> Vector<T> toVector(
+        hidl_array<T, SIZE> &array) {
+    Vector<T> vector;
+    vector.appendArray(array.data(), array.size());
+    return vector;
+}
+
+Status toStatus(status_t legacyStatus);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace drm
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_DRM_V1_0_TYPECONVERT
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service.rc b/drm/1.0/default/android.hardware.drm@1.0-service.rc
new file mode 100644
index 0000000..281dc4b
--- /dev/null
+++ b/drm/1.0/default/android.hardware.drm@1.0-service.rc
@@ -0,0 +1,6 @@
+service drm-hal-1-0 /system/bin/hw/android.hardware.drm@1.0-service
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/drm/1.0/default/service.cpp b/drm/1.0/default/service.cpp
new file mode 100644
index 0000000..d2507c4
--- /dev/null
+++ b/drm/1.0/default/service.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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 "android.hardware.drm@1.0-service"
+
+#include <1.0/default/CryptoFactory.h>
+#include <1.0/default/DrmFactory.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::registerPassthroughServiceImplementation;
+
+using android::hardware::drm::V1_0::ICryptoFactory;
+using android::hardware::drm::V1_0::IDrmFactory;
+
+int main() {
+    ALOGD("android.hardware.drm@1.0-service starting...");
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+    registerPassthroughServiceImplementation<IDrmFactory>("drm");
+    registerPassthroughServiceImplementation<ICryptoFactory>("crypto");
+    joinRpcThreadpool();
+}
diff --git a/drm/1.0/types.hal b/drm/1.0/types.hal
new file mode 100644
index 0000000..33bbf9a
--- /dev/null
+++ b/drm/1.0/types.hal
@@ -0,0 +1,336 @@
+/**
+ * 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.
+ */
+
+package android.hardware.drm@1.0;
+
+enum Status : uint32_t {
+    /**
+     * The DRM plugin must return OK when an operation completes without any
+     * errors.
+     */
+    OK,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_NO_LICENSE, when decryption is
+     * attempted and no license keys have been provided.
+     */
+    ERROR_DRM_NO_LICENSE,
+
+    /**
+     * ERROR_DRM_LICENSE_EXPIRED must be returned when an attempt is made
+     * to use a license and the keys in that license have expired.
+     */
+    ERROR_DRM_LICENSE_EXPIRED,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_SESSION_NOT_OPENED when an
+     * attempt is made to use a session that has not been opened.
+     */
+    ERROR_DRM_SESSION_NOT_OPENED,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_CANNOT_HANDLE when an unsupported
+     * data format or operation is attempted.
+     */
+    ERROR_DRM_CANNOT_HANDLE,
+
+    /**
+     * ERROR_DRM_INVALID_STATE must be returned when the device is in a state
+     * where it is not able to perform decryption.
+     */
+    ERROR_DRM_INVALID_STATE,
+
+    /**
+     * The DRM plugin must return BAD_VALUE whenever an illegal parameter is
+     * passed to one of the interface functions.
+     */
+    BAD_VALUE,
+
+    /**
+     * The DRM plugin must return ERROR_DRM_NOT_PROVISIONED from getKeyRequest,
+     * openSession or provideKeyResponse when the device has not yet been
+     * provisioned.
+     */
+    ERROR_DRM_NOT_PROVISIONED,
+
+    /**
+     * ERROR_DRM_RESOURCE_BUSY must be returned when resources, such as drm
+     * sessions or secure buffers are not available to perform a requested
+     * operation because they are already in use.
+     */
+    ERROR_DRM_RESOURCE_BUSY,
+
+    /**
+     * The DRM Plugin must return ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION
+     * when the output protection level enabled on the device is not
+     * sufficient to meet the requirements in the license policy.  HDCP is an
+     * example of a form of output protection.
+     */
+    ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION,
+
+    /**
+     * The DRM Plugin must return ERROR_DRM_DEVICE_REVOKED from
+     * provideProvisionResponse and provideKeyResponse if the response indicates
+     * that the device has been revoked. Device revocation means that the device
+     * is no longer permitted to play content.
+     */
+    ERROR_DRM_DEVICE_REVOKED,
+
+    /**
+     * ERROR_DRM_UNKNOWN must be returned when a fatal failure occurs and no
+     * other defined error is appropriate.
+     */
+    ERROR_DRM_UNKNOWN,
+};
+
+
+/**
+ * EventType enumerates the events that can be delivered by sendEvent
+ */
+enum EventType : uint32_t {
+    /**
+     * This event type indicates that the app needs to request a certificate
+     * from the provisioning server. The request message data is obtained using
+     * getProvisionRequest().
+     */
+    PROVISION_REQUIRED,
+
+     /**
+     * This event type indicates that the app needs to request keys from a
+     * license server. The request message data is obtained using getKeyRequest.
+     */
+    KEY_NEEDED,
+
+    /**
+     * This event type indicates that the licensed usage duration for keys in a
+     * session has expired. The keys are no longer valid.
+     */
+    KEY_EXPIRED,
+
+    /**
+     * This event may indicate some specific vendor-defined condition, see your
+     * DRM provider documentation for details.
+     */
+    VENDOR_DEFINED,
+
+    /**
+     * This event indicates that a session opened by the app has been reclaimed
+     * by the resource manager.
+     */
+    SESSION_RECLAIMED,
+};
+
+enum KeyType : uint32_t {
+    /**
+     * Drm keys can be for offline content or for online streaming.
+     * Offline keys are persisted on the device and may be used when the device
+     * is disconnected from the network.
+     */
+    OFFLINE,
+
+    /**
+     * Keys for streaming are not persisted and require the device to be
+     * connected to the network for periodic renewal.
+     */
+    STREAMING,
+
+    /**
+     * The Release type is used to request that offline keys be no longer
+     * restricted to offline use.
+     */
+    RELEASE,
+};
+
+/**
+ * Enumerate KeyRequestTypes to allow an app to determine the type of a key
+ * request returned from getKeyRequest.
+ */
+enum KeyRequestType : uint32_t {
+    /**
+     * Key request type is for an initial license request
+     */
+    INITIAL,
+
+    /**
+     * Key request type is for license renewal. Renewal requests are used
+     * to extend the validity period for streaming keys.
+     */
+    RENEWAL,
+
+    /**
+     * Key request type is a release. A key release causes offline keys
+     * to become available for streaming.
+     */
+    RELEASE,
+
+    /**
+     * Key request type is unknown due to some error condition.
+     */
+    UNKNOWN,
+};
+
+/**
+ * Enumerate KeyStatusTypes which indicate the state of a key
+ */
+enum KeyStatusType : uint32_t {
+    /**
+     * The key is currently usable to decrypt media data.
+     */
+    USABLE,
+
+    /**
+     * The key is no longer usable to decrypt media data because its expiration
+     * time has passed.
+     */
+    EXPIRED,
+
+    /**
+     * The key is not currently usable to decrypt media data because its output
+     * requirements cannot currently be met.
+     */
+    OUTPUTNOTALLOWED,
+
+    /**
+     * The status of the key is not yet known and is being determined.
+     */
+    STATUSPENDING,
+
+    /**
+     * The key is not currently usable to decrypt media data because of an
+     * internal error in processing unrelated to input parameters.
+     */
+    INTERNALERROR,
+};
+
+typedef vec<uint8_t> SessionId;
+
+/**
+ * Used by sendKeysChange to report the usability status of each key to the
+ * app.
+ */
+struct KeyStatus
+{
+    vec<uint8_t> keyId;
+    KeyStatusType type;
+};
+
+/**
+ * Simulates a KeyedVector<String8, String8>
+ */
+struct KeyValue {
+    string key;
+    string value;
+};
+
+typedef vec<KeyValue> KeyedVector;
+
+/**
+ * Encapsulates a secure stop opaque object
+ */
+struct SecureStop {
+    vec<uint8_t> opaqueData;
+};
+
+typedef vec<uint8_t> SecureStopId;
+
+
+/**
+ * Enumerate the supported crypto modes
+ */
+enum Mode : uint32_t {
+    UNENCRYPTED = 0, // Samples are unencrypted
+    AES_CTR     = 1, // Samples are encrypted with AES CTR mode
+    AES_CBC_CTS = 2, // Samples are encrypted with AES CBC CTS mode
+    AES_CBC     = 3, // Samples are encrypted with AES CBC mode
+};
+
+/**
+ * A subsample consists of some number of bytes of clear (unencrypted)
+ * data followed by a number of bytes of encrypted data.
+ */
+struct SubSample {
+    uint32_t numBytesOfClearData;
+    uint32_t numBytesOfEncryptedData;
+};
+
+/**
+ * A crypto Pattern is a repeating sequence of encrypted and clear blocks
+ * occuring within the bytes indicated by mNumBytesOfEncryptedDatad bytes
+ * of a subsample. Patterns are used to reduce the CPU overhead of
+ * decrypting samples. As an example, HLS uses 1:9 patterns where every
+ * 10th block is encrypted.
+ */
+struct Pattern {
+    /**
+     * The number of blocks to be encrypted in the pattern. If zero,
+     * pattern encryption is inoperative.
+     */
+    uint32_t encryptBlocks;
+
+    /**
+     * The number of blocks to be skipped (left clear) in the pattern. If
+     * zero, pattern encryption is inoperative.
+     */
+    uint32_t skipBlocks;
+};
+
+enum BufferType : uint32_t {
+    SHARED_MEMORY = 0,
+    NATIVE_HANDLE = 1,
+};
+
+/**
+ * A SharedBuffer describes a decrypt buffer which is defined by an offset and
+ * a size.  The offset is relative to the shared memory base which is established
+ * using setSharedMemoryBase().
+ */
+struct SharedBuffer {
+    /**
+     * The offset from the shared memory base
+     */
+    uint64_t offset;
+
+    /**
+     * The size of the shared buffer in bytes
+     */
+    uint64_t size;
+};
+
+
+/**
+ * A decrypt destination buffer can be either normal user-space shared
+ * memory for the non-secure decrypt case, or it can be a secure buffer
+ * which is referenced by a native-handle. The native handle is allocated
+ * by the vendor's buffer allocator.
+ */
+struct DestinationBuffer {
+    /**
+     * The type of the buffer
+     */
+    BufferType type;
+
+    /**
+     * If type == SHARED_MEMORY, the decrypted data must be written
+     * to user-space non-secure shared memory.
+     */
+    SharedBuffer nonsecureMemory;
+
+    /**
+     * If type == NATIVE_HANDLE, the decrypted data must be written
+     * to secure memory referenced by the vendor's buffer allocator.
+     */
+    handle secureMemory;
+};
diff --git a/drm/Android.bp b/drm/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/drm/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
new file mode 100644
index 0000000..7255937
--- /dev/null
+++ b/dumpstate/1.0/Android.bp
@@ -0,0 +1,52 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.dumpstate@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.dumpstate@1.0",
+    srcs: [
+        "IDumpstateDevice.hal",
+    ],
+    out: [
+        "android/hardware/dumpstate/1.0/DumpstateDeviceAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.dumpstate@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.dumpstate@1.0",
+    srcs: [
+        "IDumpstateDevice.hal",
+    ],
+    out: [
+        "android/hardware/dumpstate/1.0/IDumpstateDevice.h",
+        "android/hardware/dumpstate/1.0/IHwDumpstateDevice.h",
+        "android/hardware/dumpstate/1.0/BnHwDumpstateDevice.h",
+        "android/hardware/dumpstate/1.0/BpHwDumpstateDevice.h",
+        "android/hardware/dumpstate/1.0/BsDumpstateDevice.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.dumpstate@1.0",
+    generated_sources: ["android.hardware.dumpstate@1.0_genc++"],
+    generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/dumpstate/1.0/IDumpstateDevice.hal b/dumpstate/1.0/IDumpstateDevice.hal
new file mode 100644
index 0000000..fec3eb4
--- /dev/null
+++ b/dumpstate/1.0/IDumpstateDevice.hal
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+package android.hardware.dumpstate@1.0;
+
+interface IDumpstateDevice {
+    /*
+     * Dumps device-specific state into the given file descriptor.
+     */
+    dumpstateBoard(handle h);
+};
diff --git a/dumpstate/1.0/default/Android.mk b/dumpstate/1.0/default/Android.mk
new file mode 100644
index 0000000..0b15184
--- /dev/null
+++ b/dumpstate/1.0/default/Android.mk
@@ -0,0 +1,22 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.dumpstate@1.0-service
+LOCAL_INIT_RC := android.hardware.dumpstate@1.0-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    DumpstateDevice.cpp \
+    service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.dumpstate@1.0 \
+    libbase \
+    libcutils \
+    libdumpstateutil \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils
+
+include $(BUILD_EXECUTABLE)
diff --git a/dumpstate/1.0/default/DumpstateDevice.cpp b/dumpstate/1.0/default/DumpstateDevice.cpp
new file mode 100644
index 0000000..8000d85
--- /dev/null
+++ b/dumpstate/1.0/default/DumpstateDevice.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "dumpstate"
+
+#include "DumpstateDevice.h"
+
+#include <log/log.h>
+
+#include "DumpstateUtil.h"
+
+using android::os::dumpstate::DumpFileToFd;
+using android::os::dumpstate::RunCommandToFd;
+
+namespace android {
+namespace hardware {
+namespace dumpstate {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
+Return<void> DumpstateDevice::dumpstateBoard(const hidl_handle& handle) {
+    // NOTE: this is just an example on how to use the DumpstateUtil.h functions to implement
+    // this interface - since HIDL_FETCH_IDumpstateDevice() is not defined, this function will never
+    // be called by dumpstate.
+
+    if (handle->numFds < 1) {
+        ALOGE("no FDs\n");
+        return Void();
+    }
+
+    int fd = handle->data[0];
+    if (fd < 0) {
+        ALOGE("invalid FD: %d\n", handle->data[0]);
+        return Void();
+    }
+    ALOGD("DumpstateDevice::dumpstateBoard() FD: %d\n", fd);
+    ALOGI("Dumpstate HIDL not provided by device\n");
+    dprintf(fd, "Dumpstate HIDL not provided by device; providing bogus data.\n");
+
+    // Shows some examples on how to use the libdumpstateutil API.
+    RunCommandToFd(fd, "DATE", {"/system/bin/date"});
+    DumpFileToFd(fd, "HOSTS", "/system/etc/hosts");
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace dumpstate
+}  // namespace hardware
+}  // namespace android
diff --git a/dumpstate/1.0/default/DumpstateDevice.h b/dumpstate/1.0/default/DumpstateDevice.h
new file mode 100644
index 0000000..f8585f5
--- /dev/null
+++ b/dumpstate/1.0/default/DumpstateDevice.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
+#define ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
+
+#include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace dumpstate {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct DumpstateDevice : public IDumpstateDevice {
+    // Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
+    Return<void> dumpstateBoard(const hidl_handle& h) override;
+
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace dumpstate
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_DUMPSTATE_V1_0_DUMPSTATEDEVICE_H
diff --git a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
new file mode 100644
index 0000000..99b968e
--- /dev/null
+++ b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
@@ -0,0 +1,4 @@
+service dumpstate-1-0 /system/bin/hw/android.hardware.dumpstate@1.0-service
+    class hal
+    user system
+    group system
diff --git a/dumpstate/1.0/default/service.cpp b/dumpstate/1.0/default/service.cpp
new file mode 100644
index 0000000..0d5bd94
--- /dev/null
+++ b/dumpstate/1.0/default/service.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.dumpstate@1.0-service"
+
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "DumpstateDevice.h"
+
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::sp;
+
+int main (int /* argc */, char * /* argv */ []) {
+    sp<IDumpstateDevice> dumpstate = new DumpstateDevice;
+    configureRpcThreadpool(1, true);
+    dumpstate->registerAsService("dumpstate");
+    joinRpcThreadpool();
+}
diff --git a/dumpstate/Android.bp b/dumpstate/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/dumpstate/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/evs/1.0/Android.bp b/evs/1.0/Android.bp
new file mode 100644
index 0000000..ed29968
--- /dev/null
+++ b/evs/1.0/Android.bp
@@ -0,0 +1,80 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.evs@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.evs@1.0",
+    srcs: [
+        "types.hal",
+        "IEvsCamera.hal",
+        "IEvsCameraStream.hal",
+        "IEvsDisplay.hal",
+        "IEvsEnumerator.hal",
+    ],
+    out: [
+        "android/hardware/evs/1.0/types.cpp",
+        "android/hardware/evs/1.0/EvsCameraAll.cpp",
+        "android/hardware/evs/1.0/EvsCameraStreamAll.cpp",
+        "android/hardware/evs/1.0/EvsDisplayAll.cpp",
+        "android/hardware/evs/1.0/EvsEnumeratorAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.evs@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.evs@1.0",
+    srcs: [
+        "types.hal",
+        "IEvsCamera.hal",
+        "IEvsCameraStream.hal",
+        "IEvsDisplay.hal",
+        "IEvsEnumerator.hal",
+    ],
+    out: [
+        "android/hardware/evs/1.0/types.h",
+        "android/hardware/evs/1.0/IEvsCamera.h",
+        "android/hardware/evs/1.0/IHwEvsCamera.h",
+        "android/hardware/evs/1.0/BnHwEvsCamera.h",
+        "android/hardware/evs/1.0/BpHwEvsCamera.h",
+        "android/hardware/evs/1.0/BsEvsCamera.h",
+        "android/hardware/evs/1.0/IEvsCameraStream.h",
+        "android/hardware/evs/1.0/IHwEvsCameraStream.h",
+        "android/hardware/evs/1.0/BnHwEvsCameraStream.h",
+        "android/hardware/evs/1.0/BpHwEvsCameraStream.h",
+        "android/hardware/evs/1.0/BsEvsCameraStream.h",
+        "android/hardware/evs/1.0/IEvsDisplay.h",
+        "android/hardware/evs/1.0/IHwEvsDisplay.h",
+        "android/hardware/evs/1.0/BnHwEvsDisplay.h",
+        "android/hardware/evs/1.0/BpHwEvsDisplay.h",
+        "android/hardware/evs/1.0/BsEvsDisplay.h",
+        "android/hardware/evs/1.0/IEvsEnumerator.h",
+        "android/hardware/evs/1.0/IHwEvsEnumerator.h",
+        "android/hardware/evs/1.0/BnHwEvsEnumerator.h",
+        "android/hardware/evs/1.0/BpHwEvsEnumerator.h",
+        "android/hardware/evs/1.0/BsEvsEnumerator.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.evs@1.0",
+    generated_sources: ["android.hardware.evs@1.0_genc++"],
+    generated_headers: ["android.hardware.evs@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.evs@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/evs/1.0/IEvsCamera.hal b/evs/1.0/IEvsCamera.hal
new file mode 100644
index 0000000..a2fc565
--- /dev/null
+++ b/evs/1.0/IEvsCamera.hal
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+import IEvsCameraStream;
+
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+interface IEvsCamera {
+
+    /**
+     * Returns the ID of this camera.
+     *
+     * Returns the string id of this camera. This must be the same value as reported in
+     * the camera_id field of the CameraDesc structure by EvsEnumerator::getCamerList().
+     */
+    getId() generates (string cameraId);
+
+    /**
+     * Specifies the depth of the buffer chain the camera is asked to support.
+     *
+     * Up to this many frames may be held concurrently by the client of IEvsCamera.
+     * If this many frames have been delivered to the receiver without being returned
+     * by doneWithFrame, the stream must skip frames until a buffer is returned for reuse.
+     * It is legal for this call to come at any time, even while streams are already running,
+     * in which case buffers should be added or removed from the chain as appropriate.
+     * If no call is made to this entry point, the IEvsCamera must support at least one
+     * frame by default. More is acceptable.
+     * BUFFER_NOT_AVAILABLE is returned if the implementation cannot support the
+     * requested number of concurrent frames.
+     */
+    setMaxFramesInFlight(uint32_t bufferCount) generates (EvsResult result);
+
+    /**
+     * Request delivery of EVS camera frames from this camera.
+     *
+     * The IEvsCameraStream must begin receiving periodic calls with new image
+     * frames until stopVideoStream() is called.
+     */
+    startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
+
+    /**
+     * Return a frame that was delivered by to the IEvsCameraStream.
+     *
+     * When done consuming a frame delivered to the IEvsCameraStream
+     * interface, it must be returned to the IEvsCamera for reuse.
+     * A small, finite number of buffers are available (possibly as small
+     * as one), and if the supply is exhausted, no further frames may be
+     * delivered until a buffer is returned.
+     */
+    doneWithFrame(uint32_t frameId, handle bufferHandle) generates (EvsResult result);
+
+    /**
+     * Stop the delivery of EVS camera frames.
+     *
+     * Because delivery is asynchronous, frames may continue to arrive for
+     * some time after this call returns. Each must be returned until the
+     * closure of the stream is signaled to the IEvsCameraStream.
+     * This function cannot fail and is simply ignored if the stream isn't running.
+     */
+    stopVideoStream();
+
+    /**
+     * Request driver specific information from the HAL implementation.
+     *
+     * The values allowed for opaqueIdentifier are driver specific,
+     * but no value passed in may crash the driver. The driver should
+     * return 0 for any unrecognized opaqueIdentifier.
+     */
+    getExtendedInfo(uint32_t opaqueIdentifier) generates (int32_t value);
+
+    /**
+     * Send a driver specific value to the HAL implementation.
+     *
+     * This extension is provided to facilitate car specific
+     * extensions, but no HAL implementation may require this call
+     * in order to function in a default state.
+     * INVALID_ARG is returned if the opaqueValue is not meaningful to
+     * the driver implementation.
+     */
+    setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue) generates (EvsResult result);
+};
diff --git a/evs/1.0/IEvsCameraStream.hal b/evs/1.0/IEvsCameraStream.hal
new file mode 100644
index 0000000..ef5460f
--- /dev/null
+++ b/evs/1.0/IEvsCameraStream.hal
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+
+/**
+ * Implemented on client side to receive asynchronous video frame deliveries.
+ */
+interface IEvsCameraStream {
+
+    /**
+     * Receives calls from the HAL each time a video frame is ready for inspection.
+     * Buffer handles received by this method must be returned via calls to
+     * IEvsCamera::doneWithFrame(). When the video stream is stopped via a call
+     * to IEvsCamera::stopVideoStream(), this callback may continue to happen for
+     * some time as the pipeline drains. Each frame must still be returned.
+     * When the last frame in the stream has been delivered, a NULL bufferHandle
+     * must be delivered, signifying the end of the stream. No further frame
+     * deliveries may happen thereafter.
+     */
+    oneway deliverFrame(uint32_t frameId, handle bufferHandle);
+};
diff --git a/evs/1.0/IEvsDisplay.hal b/evs/1.0/IEvsDisplay.hal
new file mode 100644
index 0000000..a473872
--- /dev/null
+++ b/evs/1.0/IEvsDisplay.hal
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+
+
+/**
+ * Represents a single camera and is the primary interface for capturing images.
+ */
+interface IEvsDisplay {
+
+    /**
+     * Returns basic information about the EVS display provided by the system.
+     *
+     * See the description of the DisplayDesc structure below for details.
+     */
+     getDisplayInfo() generates (DisplayDesc info);
+
+
+    /**
+     * Clients may set the display state to express their desired state.
+     *
+     * The HAL implementation must gracefully accept a request for any state while in
+     * any other state, although the response may be to defer or ignore the request. The display
+     * is defined to start in the NOT_VISIBLE state upon initialization. The client is
+     * then expected to request the VISIBLE_ON_NEXT_FRAME state, and then begin providing
+     * video. When the display is no longer required, the client is expected to request
+     * the NOT_VISIBLE state after passing the last video frame.
+     * Returns INVALID_ARG if the requested state is not a recognized value.
+     */
+     setDisplayState(DisplayState state) generates (EvsResult result);
+
+
+    /**
+     * This call requests the current state of the display
+     *
+     * The HAL implementation should report the actual current state, which might
+     * transiently differ from the most recently requested state. Note, however, that
+     * the logic responsible for changing display states should generally live above
+     * the device layer, making it undesirable for the HAL implementation to spontaneously
+     * change display states.
+     */
+     getDisplayState() generates (DisplayState state);
+
+
+    /**
+     * This call returns a handle to a frame buffer associated with the display.
+     *
+     * The returned buffer may be locked and written to by software and/or GL. This buffer
+     * must be returned via a call to returnTargetBufferForDisplay() even if the
+     * display is no longer visible.
+     */
+     getTargetBuffer() generates (handle bufferHandle);
+
+
+    /**
+     * This call tells the display that the buffer is ready for display.
+     *
+     * The buffer is no longer valid for use by the client after this call.
+     * There is no maximum time the caller may hold onto the buffer before making this
+     * call. The buffer may be returned at any time and in any DisplayState, but all
+     * buffers are expected to be returned before the IEvsDisplay interface is destroyed.
+     */
+    returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
+};
diff --git a/evs/1.0/IEvsEnumerator.hal b/evs/1.0/IEvsEnumerator.hal
new file mode 100644
index 0000000..e3a1382
--- /dev/null
+++ b/evs/1.0/IEvsEnumerator.hal
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+import types;
+import IEvsCamera;
+import IEvsDisplay;
+
+
+/**
+ * Provides the mechanism for EVS camera discovery
+ */
+interface IEvsEnumerator {
+
+    /**
+     * Returns a list of all EVS cameras available to the system
+     */
+    getCameraList() generates (vec<CameraDesc> cameras);
+
+
+    /**
+     * Get the IEvsCamera associated with a cameraId from a CameraDesc
+     *
+     * Given a camera's unique cameraId from ca CameraDesc, returns
+     * the ICamera interface assocaited with the specified camera.
+     * When done using the camera, it must be returned by calling
+     * closeCamera on the ICamera interface.
+     */
+    openCamera(string cameraId) generates (IEvsCamera carCamera);
+
+    /**
+     * Return the specified IEvsCamera interface as no longer in use
+     *
+     * When the IEvsCamera object is no longer required, it must be released.
+     * NOTE: Video streaming must be cleanly stopped before making this call.
+     */
+    closeCamera(IEvsCamera carCamera);
+
+
+    /**
+     * Get exclusive access to IEvsDisplay for the system
+     *
+     * There can be at most one EVS display object for the system and this function
+     * requests access to it. If the EVS display is not available or is already in use,
+     * a null pointer is returned.
+     */
+    openDisplay() generates (IEvsDisplay display);
+
+    /**
+     * Return the specified IEvsDisplay interface as no longer in use
+     *
+     * When the IEvsDisplay object is no longer required, it must be released.
+     * NOTE: All buffer must have been returned to the display before making this call.
+     */
+    closeDisplay(IEvsDisplay display);
+};
+
diff --git a/evs/1.0/default/Android.bp b/evs/1.0/default/Android.bp
new file mode 100644
index 0000000..3bda250
--- /dev/null
+++ b/evs/1.0/default/Android.bp
@@ -0,0 +1,26 @@
+cc_binary {
+    name: "android.hardware.evs@1.0-service",
+    relative_install_path: "hw",
+    srcs: [
+        "service.cpp",
+        "EvsCamera.cpp",
+        "EvsEnumerator.cpp",
+        "EvsDisplay.cpp"
+    ],
+    init_rc: ["android.hardware.evs@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.evs@1.0",
+        "android.hardware.graphics.allocator@2.0",
+        "libui",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/evs/1.0/default/EvsCamera.cpp b/evs/1.0/default/EvsCamera.cpp
new file mode 100644
index 0000000..6715a2e
--- /dev/null
+++ b/evs/1.0/default/EvsCamera.cpp
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsCamera.h"
+
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+// These are the special camera names for which we'll initialize custom test data
+const char EvsCamera::kCameraName_Backup[]    = "backup";
+const char EvsCamera::kCameraName_RightTurn[] = "Right Turn";
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As it stands, if the client dies suddently, the buffer may be stranded.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+EvsCamera::EvsCamera(const char *id) {
+    ALOGD("EvsCamera instantiated");
+
+    mDescription.cameraId = id;
+    mFrameBusy = false;
+    mStreamState = STOPPED;
+
+    // Set up dummy data for testing
+    if (mDescription.cameraId == kCameraName_Backup) {
+        mDescription.hints                  = static_cast<uint32_t>(UsageHint::USAGE_HINT_REVERSE);
+        mDescription.vendorFlags            = 0xFFFFFFFF;   // Arbitrary value
+        mDescription.defaultHorResolution   = 320;          // 1/2 NTSC/VGA
+        mDescription.defaultVerResolution   = 240;          // 1/2 NTSC/VGA
+    }
+    else if (mDescription.cameraId == kCameraName_RightTurn) {
+        // Nothing but the name and the usage hint
+        mDescription.hints                  = static_cast<uint32_t>(UsageHint::USAGE_HINT_RIGHT_TURN);
+    }
+    else {
+        // Leave empty for a minimalist camera description without even a hint
+    }
+}
+
+EvsCamera::~EvsCamera() {
+    ALOGD("EvsCamera being destroyed");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Make sure our output stream is cleaned up
+    // (It really should be already)
+    stopVideoStream();
+
+    // Drop the graphics buffer we've been using
+    if (mBuffer) {
+        // Drop the graphics buffer we've been using
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.free(mBuffer);
+    }
+
+    ALOGD("EvsCamera destroyed");
+}
+
+
+// Methods from ::android::hardware::evs::V1_0::IEvsCamera follow.
+Return<void> EvsCamera::getId(getId_cb id_cb) {
+    ALOGD("getId");
+
+    id_cb(mDescription.cameraId);
+
+    return Void();
+}
+
+
+Return<EvsResult> EvsCamera::setMaxFramesInFlight(uint32_t bufferCount) {
+    ALOGD("setMaxFramesInFlight");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // TODO:  Update our stored value
+
+    // TODO:  Adjust our buffer count right now if we can.  Otherwise, it'll adjust in doneWithFrame
+
+    // For now we support only one!
+    if (bufferCount != 1) {
+        return EvsResult::BUFFER_NOT_AVAILABLE;
+    }
+
+    return EvsResult::OK;
+}
+
+Return<EvsResult> EvsCamera::startVideoStream(const ::android::sp<IEvsCameraStream>& stream)  {
+    ALOGD("startVideoStream");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // We only support a single stream at a time
+    if (mStreamState != STOPPED) {
+        ALOGE("ignoring startVideoStream call when a stream is already running.");
+        return EvsResult::STREAM_ALREADY_RUNNING;
+    }
+
+    // Record the user's callback for use when we have a frame ready
+    mStream = stream;
+
+    // Allocate a graphics buffer into which we'll put our test images
+    if (!mBuffer) {
+        mWidth  = (mDescription.defaultHorResolution) ? mDescription.defaultHorResolution : 640;
+        mHeight = (mDescription.defaultVerResolution) ? mDescription.defaultVerResolution : 480;
+        // TODO:  What about stride?  Assume no padding for now...
+        mStride = 4* mWidth;    // Special cased to assume 4 byte pixels with no padding for now
+
+        ALOGD("Allocating buffer for camera frame");
+        GraphicBufferAllocator &alloc(GraphicBufferAllocator::get());
+        status_t result = alloc.allocate(mWidth, mHeight,
+                                         HAL_PIXEL_FORMAT_RGBA_8888, 1, GRALLOC_USAGE_HW_TEXTURE,
+                                         &mBuffer, &mStride, 0, "EvsCamera");
+        if (result != NO_ERROR) {
+            ALOGE("Error %d allocating %d x %d graphics buffer", result, mWidth, mHeight);
+            return EvsResult::BUFFER_NOT_AVAILABLE;
+        }
+        if (!mBuffer) {
+            ALOGE("We didn't get a buffer handle back from the allocator");
+            return EvsResult::BUFFER_NOT_AVAILABLE;
+        }
+    }
+
+    // Start the frame generation thread
+    mStreamState = RUNNING;
+    mCaptureThread = std::thread([this](){GenerateFrames();});
+
+    return EvsResult::OK;
+}
+
+Return<EvsResult> EvsCamera::doneWithFrame(uint32_t /* frameId */, const hidl_handle& bufferHandle)  {
+    ALOGD("doneWithFrame");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    if (!bufferHandle)
+    {
+        ALOGE("ignoring doneWithFrame called with invalid handle");
+        return EvsResult::INVALID_ARG;
+    }
+
+    // TODO:  Track which frames we've delivered and validate this is one of them
+
+    // Mark the frame buffer as available for a new frame
+    mFrameBusy = false;
+
+    // TODO:  If we currently have too many buffers, drop this one
+
+    return EvsResult::OK;
+}
+
+Return<void> EvsCamera::stopVideoStream()  {
+    ALOGD("stopVideoStream");
+
+    bool waitForJoin = false;
+    // Lock scope
+    {
+        std::lock_guard <std::mutex> lock(mAccessLock);
+
+        if (mStreamState == RUNNING) {
+            // Tell the GenerateFrames loop we want it to stop
+            mStreamState = STOPPING;
+
+            // Note that we asked the thread to stop and should wait for it do so
+            waitForJoin = true;
+        }
+    }
+
+    if (waitForJoin) {
+        // Block outside the mutex until the "stop" flag has been acknowledged
+        // NOTE:  We won't send any more frames, but the client might still get one already in flight
+        ALOGD("Waiting for stream thread to end...");
+        mCaptureThread.join();
+
+        // Lock scope
+        {
+            std::lock_guard <std::mutex> lock(mAccessLock);
+            mStreamState = STOPPED;
+        }
+    }
+
+    return Void();
+}
+
+Return<int32_t> EvsCamera::getExtendedInfo(uint32_t opaqueIdentifier)  {
+    ALOGD("getExtendedInfo");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // For any single digit value, return the index itself as a test value
+    if (opaqueIdentifier <= 9) {
+        return opaqueIdentifier;
+    }
+
+    // Return zero by default as required by the spec
+    return 0;
+}
+
+Return<EvsResult> EvsCamera::setExtendedInfo(uint32_t /*opaqueIdentifier*/, int32_t /*opaqueValue*/)  {
+    ALOGD("setExtendedInfo");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // We don't store any device specific information in this implementation
+    return EvsResult::INVALID_ARG;
+}
+
+
+void EvsCamera::GenerateFrames() {
+    ALOGD("Frame generate loop started");
+
+    uint32_t frameNumber;
+
+    while (true) {
+        bool timeForFrame = false;
+        // Lock scope
+        {
+            std::lock_guard<std::mutex> lock(mAccessLock);
+
+            // Tick the frame counter -- rollover is tolerated
+            frameNumber = mFrameId++;
+
+            if (mStreamState != RUNNING) {
+                // Break out of our main thread loop
+                break;
+            }
+
+            if (mFrameBusy) {
+                // Can't do anything right now -- skip this frame
+                ALOGW("Skipped a frame because client hasn't returned a buffer\n");
+            }
+            else {
+                // We're going to make the frame busy
+                mFrameBusy = true;
+                timeForFrame = true;
+            }
+        }
+
+        if (timeForFrame) {
+            // Lock our output buffer for writing
+            uint32_t *pixels = nullptr;
+            GraphicBufferMapper &mapper = GraphicBufferMapper::get();
+            mapper.lock(mBuffer,
+                        GRALLOC_USAGE_SW_WRITE_OFTEN,
+                        android::Rect(mWidth, mHeight),
+                        (void **) &pixels);
+
+            // If we failed to lock the pixel buffer, we're about to crash, but log it first
+            if (!pixels) {
+                ALOGE("Camera failed to gain access to image buffer for writing");
+            }
+
+            // Fill in the test pixels
+            for (unsigned row = 0; row < mHeight; row++) {
+                for (unsigned col = 0; col < mWidth; col++) {
+                    // Index into the row to set the pixel at this column
+                    // (We're making vertical gradient in the green channel, and
+                    // horitzontal gradient in the blue channel)
+                    pixels[col] = 0xFF0000FF | ((row & 0xFF) << 16) | ((col & 0xFF) << 8);
+                }
+                // Point to the next row
+                pixels = pixels + (mStride / sizeof(*pixels));
+            }
+
+            // Release our output buffer
+            mapper.unlock(mBuffer);
+
+            // Issue the (asynchronous) callback to the client
+            mStream->deliverFrame(frameNumber, mBuffer);
+            ALOGD("Delivered %p as frame %d", mBuffer, frameNumber);
+        }
+
+        // We arbitrarily choose to generate frames at 10 fps (1/10 * uSecPerSec)
+        usleep(100000);
+    }
+
+    // If we've been asked to stop, send one last NULL frame to signal the actual end of stream
+    mStream->deliverFrame(frameNumber, nullptr);
+
+    return;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsCamera.h b/evs/1.0/default/EvsCamera.h
new file mode 100644
index 0000000..5d29125
--- /dev/null
+++ b/evs/1.0/default/EvsCamera.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
+
+#include <android/hardware/evs/1.0/types.h>
+#include <android/hardware/evs/1.0/IEvsCamera.h>
+#include <ui/GraphicBuffer.h>
+
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsCamera : public IEvsCamera {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsCamera follow.
+    Return<void> getId(getId_cb id_cb)  override;
+    Return<EvsResult> setMaxFramesInFlight(uint32_t bufferCount)  override;
+    Return<EvsResult> startVideoStream(const ::android::sp<IEvsCameraStream>& stream) override;
+    Return<EvsResult> doneWithFrame(uint32_t frameId, const hidl_handle& bufferHandle)  override;
+    Return<void> stopVideoStream()  override;
+    Return<int32_t> getExtendedInfo(uint32_t opaqueIdentifier)  override;
+    Return<EvsResult> setExtendedInfo(uint32_t opaqueIdentifier, int32_t opaqueValue)  override;
+
+    // Implementation details
+    EvsCamera(const char* id);
+    virtual ~EvsCamera() override;
+
+    const CameraDesc& getDesc() { return mDescription; };
+    void GenerateFrames();
+
+    static const char kCameraName_Backup[];
+    static const char kCameraName_RightTurn[];
+
+private:
+    CameraDesc              mDescription = {};  // The properties of this camera
+
+    buffer_handle_t         mBuffer = nullptr;  // A graphics buffer into which we'll store images
+    uint32_t                mWidth  = 0;        // number of pixels across the buffer
+    uint32_t                mHeight = 0;        // number of pixels vertically in the buffer
+    uint32_t                mStride = 0;        // Bytes per line in the buffer
+
+    sp<IEvsCameraStream>    mStream = nullptr;  // The callback the user expects when a frame is ready
+
+    std::thread             mCaptureThread;     // The thread we'll use to synthesize frames
+
+    uint32_t                mFrameId;           // A frame counter used to identify specific frames
+
+    enum StreamStateValues {
+        STOPPED,
+        RUNNING,
+        STOPPING,
+    };
+    StreamStateValues       mStreamState;
+    bool                    mFrameBusy;         // A flag telling us our one buffer is in use
+
+    std::mutex              mAccessLock;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSCAMERA_H
diff --git a/evs/1.0/default/EvsDisplay.cpp b/evs/1.0/default/EvsDisplay.cpp
new file mode 100644
index 0000000..9dba6fc
--- /dev/null
+++ b/evs/1.0/default/EvsDisplay.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsDisplay.h"
+
+#include <ui/GraphicBufferAllocator.h>
+#include <ui/GraphicBufferMapper.h>
+
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As it stands, if the client dies suddently, the buffer may be stranded.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+
+EvsDisplay::EvsDisplay() {
+    ALOGD("EvsDisplay instantiated");
+
+    // Set up our self description
+    mInfo.displayId             = "Mock Display";
+    mInfo.vendorFlags           = 3870;
+    mInfo.defaultHorResolution  = 320;
+    mInfo.defaultVerResolution  = 240;
+}
+
+
+EvsDisplay::~EvsDisplay() {
+    ALOGD("EvsDisplay being destroyed");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Report if we're going away while a buffer is outstanding.  This could be bad.
+    if (mFrameBusy) {
+        ALOGE("EvsDisplay going down while client is holding a buffer\n");
+    }
+
+    // Make sure we release our frame buffer
+    if (mBuffer) {
+        // Drop the graphics buffer we've been using
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.free(mBuffer);
+    }
+    ALOGD("EvsDisplay destroyed");
+}
+
+
+/**
+ * Returns basic information about the EVS display provided by the system.
+ * See the description of the DisplayDesc structure below for details.
+ */
+Return<void> EvsDisplay::getDisplayInfo(getDisplayInfo_cb _hidl_cb)  {
+    ALOGD("getDisplayInfo");
+
+    // Send back our self description
+    _hidl_cb(mInfo);
+    return Void();
+}
+
+
+/**
+ * Clients may set the display state to express their desired state.
+ * The HAL implementation must gracefully accept a request for any state
+ * while in any other state, although the response may be to ignore the request.
+ * The display is defined to start in the NOT_VISIBLE state upon initialization.
+ * The client is then expected to request the VISIBLE_ON_NEXT_FRAME state, and
+ * then begin providing video.  When the display is no longer required, the client
+ * is expected to request the NOT_VISIBLE state after passing the last video frame.
+ */
+Return<EvsResult> EvsDisplay::setDisplayState(DisplayState state) {
+    ALOGD("setDisplayState");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // Ensure we recognize the requested state so we don't go off the rails
+    if (state < DisplayState::NUM_STATES) {
+        // Record the requested state
+        mRequestedState = state;
+        return EvsResult::OK;
+    }
+    else {
+        // Turn off the display if asked for an unrecognized state
+        mRequestedState = DisplayState::NOT_VISIBLE;
+        return EvsResult::INVALID_ARG;
+    }
+}
+
+
+/**
+ * The HAL implementation should report the actual current state, which might
+ * transiently differ from the most recently requested state.  Note, however, that
+ * the logic responsible for changing display states should generally live above
+ * the device layer, making it undesirable for the HAL implementation to
+ * spontaneously change display states.
+ */
+Return<DisplayState> EvsDisplay::getDisplayState()  {
+    ALOGD("getDisplayState");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // At the moment, we treat the requested state as immediately active
+    DisplayState currentState = mRequestedState;
+
+    return currentState;
+}
+
+
+/**
+ * This call returns a handle to a frame buffer associated with the display.
+ * This buffer may be locked and written to by software and/or GL.  This buffer
+ * must be returned via a call to returnTargetBufferForDisplay() even if the
+ * display is no longer visible.
+ */
+// TODO: We need to know if/when our client dies so we can get the buffer back! (blocked b/31632518)
+Return<void> EvsDisplay::getTargetBuffer(getTargetBuffer_cb _hidl_cb)  {
+    ALOGD("getTargetBuffer");
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // If we don't already have a buffer, allocate one now
+    if (!mBuffer) {
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        status_t result = alloc.allocate(mInfo.defaultHorResolution, mInfo.defaultVerResolution,
+                                         HAL_PIXEL_FORMAT_RGBA_8888, 1,
+                                         GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_COMPOSER,
+                                         &mBuffer, &mStride, 0, "EvsDisplay");
+        mFrameBusy = false;
+        ALOGD("Allocated new buffer %p with stride %u", mBuffer, mStride);
+    }
+
+    // Do we have a frame available?
+    if (mFrameBusy) {
+        // This means either we have a 2nd client trying to compete for buffers
+        // (an unsupported mode of operation) or else the client hasn't returned
+        // a previously issues buffer yet (they're behaving badly).
+        // NOTE:  We have to make callback even if we have nothing to provide
+        ALOGE("getTargetBuffer called while no buffers available.");
+        _hidl_cb(nullptr);
+    }
+    else {
+        // Mark our buffer as busy
+        mFrameBusy = true;
+
+        // Send the buffer to the client
+        ALOGD("Providing display buffer %p", mBuffer);
+        _hidl_cb(mBuffer);
+    }
+
+    // All done
+    return Void();
+}
+
+
+/**
+ * This call tells the display that the buffer is ready for display.
+ * The buffer is no longer valid for use by the client after this call.
+ */
+Return<EvsResult> EvsDisplay::returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  {
+    ALOGD("returnTargetBufferForDisplay %p", bufferHandle.getNativeHandle());
+    std::lock_guard<std::mutex> lock(mAccessLock);
+
+    // This shouldn't happen if we haven't issued the buffer!
+    if (!bufferHandle) {
+        ALOGE ("returnTargetBufferForDisplay called without a valid buffer handle.\n");
+        return EvsResult::INVALID_ARG;
+    }
+    /* TODO(b/33492405): It would be nice to validate we got back the buffer we expect,
+     * but HIDL doesn't support that (yet?)
+    if (bufferHandle != mBuffer) {
+        ALOGE ("Got an unrecognized frame returned.\n");
+        return EvsResult::INVALID_ARG;
+    }
+    */
+    if (!mFrameBusy) {
+        ALOGE ("A frame was returned with no outstanding frames.\n");
+        return EvsResult::BUFFER_NOT_AVAILABLE;
+    }
+
+    mFrameBusy = false;
+
+    // If we were waiting for a new frame, this is it!
+    if (mRequestedState == DisplayState::VISIBLE_ON_NEXT_FRAME) {
+        mRequestedState = DisplayState::VISIBLE;
+    }
+
+    // Validate we're in an expected state
+    if (mRequestedState != DisplayState::VISIBLE) {
+        // We shouldn't get frames back when we're not visible.
+        ALOGE ("Got an unexpected frame returned while not visible - ignoring.\n");
+    }
+    else {
+        // Make this buffer visible
+        // TODO:  Add code to put this image on the screen (or validate it somehow?)
+    }
+
+    return EvsResult::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsDisplay.h b/evs/1.0/default/EvsDisplay.h
new file mode 100644
index 0000000..a2d5d3e
--- /dev/null
+++ b/evs/1.0/default/EvsDisplay.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
+
+#include <android/hardware/evs/1.0/IEvsDisplay.h>
+#include <ui/GraphicBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsDisplay : public IEvsDisplay {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsDisplay follow.
+    Return<void> getDisplayInfo(getDisplayInfo_cb _hidl_cb)  override;
+    Return<EvsResult> setDisplayState(DisplayState state)  override;
+    Return<DisplayState> getDisplayState()  override;
+    Return<void> getTargetBuffer(getTargetBuffer_cb _hidl_cb)  override;
+    Return<EvsResult> returnTargetBufferForDisplay(const hidl_handle& bufferHandle)  override;
+
+    // Implementation details
+    EvsDisplay();
+    virtual ~EvsDisplay() override;
+
+private:
+    DisplayDesc     mInfo           = {};
+    buffer_handle_t mBuffer         = nullptr;      // A graphics buffer into which we'll store images
+    uint32_t        mStride         = 0;            // Bytes per line in the buffer
+
+    bool            mFrameBusy      = false;        // A flag telling us our buffer is in use
+    DisplayState    mRequestedState = DisplayState::NOT_VISIBLE;
+
+    std::mutex      mAccessLock;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSDISPLAY_H
diff --git a/evs/1.0/default/EvsEnumerator.cpp b/evs/1.0/default/EvsEnumerator.cpp
new file mode 100644
index 0000000..ba8da00
--- /dev/null
+++ b/evs/1.0/default/EvsEnumerator.cpp
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include "EvsEnumerator.h"
+#include "EvsCamera.h"
+#include "EvsDisplay.h"
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+
+EvsEnumerator::EvsEnumerator() {
+    ALOGD("EvsEnumerator created");
+
+    // Add sample camera data to our list of cameras
+    // NOTE:  The id strings trigger special initialization inside the EvsCamera constructor
+    mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_Backup),    false );
+    mCameraList.emplace_back( new EvsCamera("LaneView"),                       false );
+    mCameraList.emplace_back( new EvsCamera(EvsCamera::kCameraName_RightTurn), false );
+}
+
+// Methods from ::android::hardware::evs::V1_0::IEvsEnumerator follow.
+Return<void> EvsEnumerator::getCameraList(getCameraList_cb _hidl_cb)  {
+    ALOGD("getCameraList");
+
+    const unsigned numCameras = mCameraList.size();
+
+    // Build up a packed array of CameraDesc for return
+    // NOTE:  Only has to live until the callback returns
+    std::vector<CameraDesc> descriptions;
+    descriptions.reserve(numCameras);
+    for (const auto& cam : mCameraList) {
+        descriptions.push_back( cam.pCamera->getDesc() );
+    }
+
+    // Encapsulate our camera descriptions in the HIDL vec type
+    hidl_vec<CameraDesc> hidlCameras(descriptions);
+
+    // Send back the results
+    ALOGD("reporting %zu cameras available", hidlCameras.size());
+    _hidl_cb(hidlCameras);
+
+    // HIDL convention says we return Void if we sent our result back via callback
+    return Void();
+}
+
+Return<sp<IEvsCamera>> EvsEnumerator::openCamera(const hidl_string& cameraId) {
+    ALOGD("openCamera");
+
+    // Find the named camera
+    CameraRecord *pRecord = nullptr;
+    for (auto &&cam : mCameraList) {
+        if (cam.pCamera->getDesc().cameraId == cameraId) {
+            // Found a match!
+            pRecord = &cam;
+            break;
+        }
+    }
+
+    if (!pRecord) {
+        ALOGE("Requested camera %s not found", cameraId.c_str());
+        return nullptr;
+    }
+    else if (pRecord->inUse) {
+        ALOGE("Cannot open camera %s which is already in use", cameraId.c_str());
+        return nullptr;
+    }
+    else {
+        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
+        pRecord->inUse = true;
+         */
+        return(pRecord->pCamera);
+    }
+}
+
+Return<void> EvsEnumerator::closeCamera(const ::android::sp<IEvsCamera>& camera) {
+    ALOGD("closeCamera");
+
+    if (camera == nullptr) {
+        ALOGE("Ignoring call to closeCamera with null camera pointer");
+    }
+    else {
+        // Make sure the camera has stopped streaming
+        camera->stopVideoStream();
+
+        /* TODO(b/33492405):  Do this, When HIDL can give us back a recognizable pointer
+        pRecord->inUse = false;
+         */
+    }
+
+    return Void();
+}
+
+Return<sp<IEvsDisplay>> EvsEnumerator::openDisplay() {
+    ALOGD("openDisplay");
+
+    // If we already have a display active, then this request must be denied
+    if (mActiveDisplay != nullptr) {
+        ALOGW("Rejecting openDisplay request the display is already in use.");
+        return nullptr;
+    }
+    else {
+        // Create a new display interface and return it
+        mActiveDisplay = new EvsDisplay();
+        ALOGD("Returning new EvsDisplay object %p", mActiveDisplay.get());
+        return mActiveDisplay;
+    }
+}
+
+Return<void> EvsEnumerator::closeDisplay(const ::android::sp<IEvsDisplay>& display) {
+    ALOGD("closeDisplay");
+
+    if (mActiveDisplay == nullptr) {
+        ALOGE("Ignoring closeDisplay when display is not active");
+    }
+    else if (display == nullptr) {
+        ALOGE("Ignoring closeDisplay with null display pointer");
+    }
+    else {
+        // Drop the active display
+        // TODO(b/33492405):  When HIDL provides recognizable pointers, add validation here.
+        mActiveDisplay = nullptr;
+    }
+
+    return Void();
+}
+
+
+// TODO(b/31632518):  Need to get notification when our client dies so we can close the camera.
+// As possible work around would be to give the client a HIDL object to exclusively hold
+// and use it's destructor to perform some work in the server side.
+
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
diff --git a/evs/1.0/default/EvsEnumerator.h b/evs/1.0/default/EvsEnumerator.h
new file mode 100644
index 0000000..90df837
--- /dev/null
+++ b/evs/1.0/default/EvsEnumerator.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
+#define ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
+
+#include <android/hardware/evs/1.0/IEvsEnumerator.h>
+#include <android/hardware/evs/1.0/IEvsCamera.h>
+
+#include <list>
+
+#include "EvsCamera.h"
+
+namespace android {
+namespace hardware {
+namespace evs {
+namespace V1_0 {
+namespace implementation {
+
+class EvsEnumerator : public IEvsEnumerator {
+public:
+    // Methods from ::android::hardware::evs::V1_0::IEvsEnumerator follow.
+    Return<void> getCameraList(getCameraList_cb _hidl_cb)  override;
+    Return<sp<IEvsCamera>> openCamera(const hidl_string& cameraId) override;
+    Return<void> closeCamera(const ::android::sp<IEvsCamera>& carCamera)  override;
+    Return<sp<IEvsDisplay>> openDisplay()  override;
+    Return<void> closeDisplay(const ::android::sp<IEvsDisplay>& display)  override;
+
+    // Implementation details
+    EvsEnumerator();
+
+private:
+    struct CameraRecord {
+        sp<EvsCamera>   pCamera;
+        bool            inUse;
+        CameraRecord(EvsCamera* p, bool b) : pCamera(p), inUse(b) {}
+    };
+    std::list<CameraRecord> mCameraList;
+
+    sp<IEvsDisplay>         mActiveDisplay;
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace evs
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_EVS_V1_0_EVSCAMERAENUMERATOR_H
diff --git a/evs/1.0/default/ServiceNames.h b/evs/1.0/default/ServiceNames.h
new file mode 100644
index 0000000..d20a37f
--- /dev/null
+++ b/evs/1.0/default/ServiceNames.h
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+const static char kEnumeratorServiceName[] = "EvsEnumeratorHw-Mock";
diff --git a/evs/1.0/default/android.hardware.evs@1.0-service.rc b/evs/1.0/default/android.hardware.evs@1.0-service.rc
new file mode 100644
index 0000000..be7c9f9
--- /dev/null
+++ b/evs/1.0/default/android.hardware.evs@1.0-service.rc
@@ -0,0 +1,4 @@
+service evs-hal-1-0 /system/bin/hw/android.hardware.evs@1.0-service
+    class hal
+    user cameraserver
+    group camera
diff --git a/evs/1.0/default/service.cpp b/evs/1.0/default/service.cpp
new file mode 100644
index 0000000..112c879
--- /dev/null
+++ b/evs/1.0/default/service.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.evs@1.0-service"
+
+#include <unistd.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+#include <utils/Log.h>
+
+#include "ServiceNames.h"
+#include "EvsEnumerator.h"
+#include "EvsDisplay.h"
+
+
+// libhidl:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::evs::V1_0::IEvsEnumerator;
+using android::hardware::evs::V1_0::IEvsDisplay;
+
+// The namespace in which all our implementation code lives
+using namespace android::hardware::evs::V1_0::implementation;
+using namespace android;
+
+
+int main() {
+    ALOGI("EVS Hardware Enumerator service is starting");
+    android::sp<IEvsEnumerator> service = new EvsEnumerator();
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+
+    // Register our service -- if somebody is already registered by our name,
+    // they will be killed (their thread pool will throw an exception).
+    status_t status = service->registerAsService(kEnumeratorServiceName);
+    if (status == OK) {
+        ALOGD("%s is ready.", kEnumeratorServiceName);
+        joinRpcThreadpool();
+    } else {
+        ALOGE("Could not register service %s (%d).", kEnumeratorServiceName, status);
+    }
+
+    // In normal operation, we don't expect the thread pool to exit
+    ALOGE("EVS Hardware Enumerator is shutting down");
+    return 1;
+}
diff --git a/evs/1.0/types.hal b/evs/1.0/types.hal
new file mode 100644
index 0000000..fd9dcdc
--- /dev/null
+++ b/evs/1.0/types.hal
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+package android.hardware.evs@1.0;
+
+
+/*
+ * Bit flags indicating suggested uses for a given EVS camera
+ *
+ * The values in the UsageHint bit field provide a generic expression of how a
+ * given camera is intended to be used. The values for these flags support
+ * existing use cases, and are used by the default EVS application to select
+ * appropriate cameras for display based on observed vehicle state (such as
+ * turn signal activation or selection of reverse gear). When implementing
+ * their own specialized EVS Applications, OEMs are free to use these flags
+ * and/or the opaque vendor_flags to drive their own vehicle specific logic.
+ */
+enum UsageHint : uint32_t {
+    USAGE_HINT_REVERSE      = 0x00000001,
+    USAGE_HINT_LEFT_TURN    = 0x00000002,
+    USAGE_HINT_RIGHT_TURN   = 0x00000004,
+};
+
+
+/*
+ * Structure describing the basic properties of an EVS camera
+ *
+ * The HAL is responsible for filling out this structure for each
+ * EVS camera in the system. Attention should be given to the field
+ * of view, direction of view, and location parameters as these may
+ * be used to (if available) to project overlay graphics into the
+ * scene by an EVS application.
+ * Any of these values for which the HAL does not have reasonable values
+ * should be set to ZERO.
+ */
+struct CameraDesc {
+    string              cameraId;
+    bitfield<UsageHint> hints;                  // Mask of usage hints
+    uint32_t            vendorFlags;            // Opaque value from driver
+    uint32_t            defaultHorResolution;   // Units of pixels
+    uint32_t            defaultVerResolution;   // Units of pixels
+};
+
+
+/*
+ * Structure describing the basic properties of an EVS display
+ *
+ * The HAL is responsible for filling out this structure to describe
+ * the EVS display. As an implementation detail, this may be a physical
+ * display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+struct DisplayDesc {
+    string      displayId;
+    uint32_t    vendorFlags;                // Opaque value from driver
+    uint32_t    defaultHorResolution;       // Units of pixels
+    uint32_t    defaultVerResolution;       // Units of pixels
+};
+
+
+/*
+ * States for control of the EVS display
+ *
+ * The DisplayInfo structure describes the basic properties of an EVS display. Any EVS
+ * implementation is required to have one. The HAL is responsible for filling out this
+ * structure to describe the EVS display. As an implementation detail, this may be a
+ * physical display or a virtual display that is overlaid or mixed with another
+ * presentation device.
+ */
+enum DisplayState : uint32_t {
+    NOT_VISIBLE = 0,        // Display is inhibited
+    VISIBLE_ON_NEXT_FRAME,  // Will become visible with next frame
+    VISIBLE,                // Display is currently active
+    NUM_STATES              // Must be last
+};
+
+
+/* Error codes used in EVS HAL interface. */
+enum EvsResult : uint32_t {
+    OK = 0,
+    INVALID_ARG,
+    STREAM_ALREADY_RUNNING,
+    BUFFER_NOT_AVAILABLE,
+};
\ No newline at end of file
diff --git a/evs/Android.bp b/evs/Android.bp
new file mode 100644
index 0000000..ba90f2c
--- /dev/null
+++ b/evs/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+]
diff --git a/example/Android.bp b/example/Android.bp
new file mode 100644
index 0000000..ea6dbb5
--- /dev/null
+++ b/example/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "extension/light/2.0",
+]
diff --git a/example/extension/light/2.0/Android.bp b/example/extension/light/2.0/Android.bp
new file mode 100644
index 0000000..cc50b83
--- /dev/null
+++ b/example/extension/light/2.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.example.extension.light@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.example.extension.light@2.0",
+    srcs: [
+        "types.hal",
+        "IExtLight.hal",
+    ],
+    out: [
+        "android/hardware/example/extension/light/2.0/types.cpp",
+        "android/hardware/example/extension/light/2.0/ExtLightAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.example.extension.light@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.example.extension.light@2.0",
+    srcs: [
+        "types.hal",
+        "IExtLight.hal",
+    ],
+    out: [
+        "android/hardware/example/extension/light/2.0/types.h",
+        "android/hardware/example/extension/light/2.0/IExtLight.h",
+        "android/hardware/example/extension/light/2.0/IHwExtLight.h",
+        "android/hardware/example/extension/light/2.0/BnHwExtLight.h",
+        "android/hardware/example/extension/light/2.0/BpHwExtLight.h",
+        "android/hardware/example/extension/light/2.0/BsExtLight.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.example.extension.light@2.0",
+    generated_sources: ["android.hardware.example.extension.light@2.0_genc++"],
+    generated_headers: ["android.hardware.example.extension.light@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.example.extension.light@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.light@2.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.light@2.0",
+    ],
+}
diff --git a/example/extension/light/2.0/Android.mk b/example/extension/light/2.0/Android.mk
new file mode 100644
index 0000000..deb7a2a
--- /dev/null
+++ b/example/extension/light/2.0/Android.mk
@@ -0,0 +1,196 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.example.extension.light@2.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hardware.light@2.0-java \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (Default)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/Default.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.Default
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ExtBrightness)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/ExtBrightness.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.ExtBrightness
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ExtLightState)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/ExtLightState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.ExtLightState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IExtLight.hal
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/IExtLight.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IExtLight.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::IExtLight
+
+$(GEN): $(LOCAL_PATH)/IExtLight.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.example.extension.light@2.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hardware.light@2.0-java-static \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (Default)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/Default.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.Default
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ExtBrightness)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/ExtBrightness.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.ExtBrightness
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ExtLightState)
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/ExtLightState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::types.ExtLightState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IExtLight.hal
+#
+GEN := $(intermediates)/android/hardware/example/extension/light/V2_0/IExtLight.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IExtLight.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.example.extension.light@2.0::IExtLight
+
+$(GEN): $(LOCAL_PATH)/IExtLight.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/example/extension/light/2.0/IExtLight.hal b/example/extension/light/2.0/IExtLight.hal
new file mode 100644
index 0000000..f12a272
--- /dev/null
+++ b/example/extension/light/2.0/IExtLight.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+// Would normally be 'vendor.example.extension.light@2.0' however, this is
+// a google extension example. A vendor extension should also live in the
+// vendor partition.
+package android.hardware.example.extension.light@2.0;
+
+import android.hardware.light@2.0;
+
+interface IExtLight extends android.hardware.light@2.0::ILight {
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * @param type logical light to set
+     * @param state describes what the light should look like.
+     * @return status result of applying state transformation.
+     */
+    setExtLight(Type type, ExtLightState state) generates (Status status);
+
+};
diff --git a/example/extension/light/2.0/default/Android.mk b/example/extension/light/2.0/default/Android.mk
new file mode 100644
index 0000000..55c21b9
--- /dev/null
+++ b/example/extension/light/2.0/default/Android.mk
@@ -0,0 +1,18 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.example.extension.light@2.0-service
+LOCAL_INIT_RC := android.hardware.example.extension.light@2.0-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    Light.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    android.hardware.light@2.0 \
+    android.hardware.example.extension.light@2.0 \
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/example/extension/light/2.0/default/Light.cpp b/example/extension/light/2.0/default/Light.cpp
new file mode 100644
index 0000000..2e56319
--- /dev/null
+++ b/example/extension/light/2.0/default/Light.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+#include "Light.h"
+
+namespace android {
+namespace hardware {
+namespace example {
+namespace extension {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::light::V2_0::ILight follow.
+Return<Status> Light::setLight(Type type, const LightState& state)  {
+    // Forward types for new methods.
+
+    ExtLightState extState {
+        .state = state,
+        .interpolationOmega =
+            static_cast<int32_t>(Default::INTERPOLATION_OMEGA),
+        .brightness = // ExtBrightness inherits from Brightness
+            static_cast<ExtBrightness>(state.brightnessMode)
+    };
+
+    return setExtLight(type, extState);
+}
+
+Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb)  {
+    // implement unchanged method as you would always
+    hidl_vec<Type> vec{};
+
+    // ******************************************************
+    // Note: awesome proprietary hardware implementation here
+    // ******************************************************
+
+    _hidl_cb(vec);
+
+    return Void();
+}
+
+// Methods from ::android::hardware::example::extension::light::V2_0::ILight follow.
+Return<Status> Light::setExtLight(Type /* type */,
+                                  const ExtLightState& /* state */)  {
+
+    // ******************************************************
+    // Note: awesome proprietary hardware implementation here
+    // ******************************************************
+
+    return Status::SUCCESS;
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace light
+}  // namespace extension
+}  // namespace example
+}  // namespace hardware
+}  // namespace android
diff --git a/example/extension/light/2.0/default/Light.h b/example/extension/light/2.0/default/Light.h
new file mode 100644
index 0000000..e3b60df
--- /dev/null
+++ b/example/extension/light/2.0/default/Light.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_EXAMPLE_EXTENSION_LIGHT_V2_0_LIGHT_H
+#define ANDROID_HARDWARE_EXAMPLE_EXTENSION_LIGHT_V2_0_LIGHT_H
+
+#include <android/hardware/example/extension/light/2.0/IExtLight.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace example {
+namespace extension {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::example::extension::light::V2_0::ExtLightState;
+using ::android::hardware::example::extension::light::V2_0::IExtLight;
+using ::android::hardware::light::V2_0::ILight;
+using ::android::hardware::light::V2_0::LightState;
+using ::android::hardware::light::V2_0::Status;
+using ::android::hardware::light::V2_0::Type;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Light : public IExtLight {
+    // Methods from ::android::hardware::light::V2_0::ILight follow.
+    Return<Status> setLight(Type type, const LightState& state)  override;
+    Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;
+
+    // Methods from ::android::hardware::example::extension::light::V2_0::ILight follow.
+    Return<Status> setExtLight(Type type, const ExtLightState& state)  override;
+
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace light
+}  // namespace extension
+}  // namespace example
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_EXAMPLE_EXTENSION_LIGHT_V2_0_LIGHT_H
diff --git a/example/extension/light/2.0/default/android.hardware.example.extension.light@2.0-service.rc b/example/extension/light/2.0/default/android.hardware.example.extension.light@2.0-service.rc
new file mode 100644
index 0000000..8a90d81
--- /dev/null
+++ b/example/extension/light/2.0/default/android.hardware.example.extension.light@2.0-service.rc
@@ -0,0 +1,4 @@
+service light-ext-2-0 /system/bin/hw/android.hardware.example.extension.light@2.0-service
+    class hal
+    user system
+    group system readproc
\ No newline at end of file
diff --git a/example/extension/light/2.0/default/service.cpp b/example/extension/light/2.0/default/service.cpp
new file mode 100644
index 0000000..d3fb4de
--- /dev/null
+++ b/example/extension/light/2.0/default/service.cpp
@@ -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.
+ */
+#define LOG_TAG "android.hardware.light@2.0-service"
+
+#include <android/log.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "Light.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::sp;
+
+// Generated HIDL files
+using android::hardware::light::V2_0::ILight;
+
+int main() {
+    const char instance[] = "light";
+
+    android::sp<ILight> service = new Light();
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+    service->registerAsService(instance);
+    joinRpcThreadpool();
+}
diff --git a/example/extension/light/2.0/types.hal b/example/extension/light/2.0/types.hal
new file mode 100644
index 0000000..5be41bb
--- /dev/null
+++ b/example/extension/light/2.0/types.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.example.extension.light@2.0;
+
+import android.hardware.light@2.0;
+
+enum Default : int32_t {
+    // for calls to setLight from the framework that don't know about this
+    // extension or its requirements
+    INTERPOLATION_OMEGA = 2
+};
+
+/**
+ * One possibility is renaming an old type. Another possibility is taking
+ * advantages of the different namespaces.
+ */
+enum ExtBrightness : Brightness {
+    /**
+     * Say we're really going to use the phone as a heater.
+     */
+    EXTREME,
+
+    /**
+     * Sometimes at night, we need it to be day.
+     */
+     THE_SUN,
+};
+
+/**
+ * Structs can't inherit eachother in hidl. Use composition instead. In this
+ * case, I won't use inheritence because I want to replace Brightness with
+ * ExtBrightness.
+ */
+struct ExtLightState {
+    LightState state;
+
+    /**
+     * This is the secret sauce that will really make this extension shine.
+     * No other person has such a cool feature in their hals. Don't forget
+     * to describe all details of parameters. An interface is a contract, and
+     * specifying this contract to the letter is what allows that contracted
+     * to be maintained. :)
+     *
+     * So, this parameter represents the speed at which brightness is changed
+     * to the new value in the three dimensional space with coordinates RGB
+     * from the red, blue, and green.
+     */
+    int32_t interpolationOmega;
+
+    /**
+     * Include new values.
+     */
+    ExtBrightness brightness;
+};
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
new file mode 100644
index 0000000..8ef33ab
--- /dev/null
+++ b/gatekeeper/1.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.gatekeeper@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.gatekeeper@1.0",
+    srcs: [
+        "types.hal",
+        "IGatekeeper.hal",
+    ],
+    out: [
+        "android/hardware/gatekeeper/1.0/types.cpp",
+        "android/hardware/gatekeeper/1.0/GatekeeperAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.gatekeeper@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.gatekeeper@1.0",
+    srcs: [
+        "types.hal",
+        "IGatekeeper.hal",
+    ],
+    out: [
+        "android/hardware/gatekeeper/1.0/types.h",
+        "android/hardware/gatekeeper/1.0/IGatekeeper.h",
+        "android/hardware/gatekeeper/1.0/IHwGatekeeper.h",
+        "android/hardware/gatekeeper/1.0/BnHwGatekeeper.h",
+        "android/hardware/gatekeeper/1.0/BpHwGatekeeper.h",
+        "android/hardware/gatekeeper/1.0/BsGatekeeper.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.gatekeeper@1.0",
+    generated_sources: ["android.hardware.gatekeeper@1.0_genc++"],
+    generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/gatekeeper/1.0/Android.mk b/gatekeeper/1.0/Android.mk
new file mode 100644
index 0000000..5d66b45
--- /dev/null
+++ b/gatekeeper/1.0/Android.mk
@@ -0,0 +1,156 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gatekeeper@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (GatekeeperResponse)
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/GatekeeperResponse.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::types.GatekeeperResponse
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GatekeeperStatusCode)
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/GatekeeperStatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::types.GatekeeperStatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGatekeeper.hal
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/IGatekeeper.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGatekeeper.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::IGatekeeper
+
+$(GEN): $(LOCAL_PATH)/IGatekeeper.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gatekeeper@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (GatekeeperResponse)
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/GatekeeperResponse.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::types.GatekeeperResponse
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GatekeeperStatusCode)
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/GatekeeperStatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::types.GatekeeperStatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGatekeeper.hal
+#
+GEN := $(intermediates)/android/hardware/gatekeeper/V1_0/IGatekeeper.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGatekeeper.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gatekeeper@1.0::IGatekeeper
+
+$(GEN): $(LOCAL_PATH)/IGatekeeper.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/gatekeeper/1.0/IGatekeeper.hal b/gatekeeper/1.0/IGatekeeper.hal
new file mode 100644
index 0000000..c193477
--- /dev/null
+++ b/gatekeeper/1.0/IGatekeeper.hal
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+package android.hardware.gatekeeper@1.0;
+
+interface IGatekeeper {
+
+/**
+ * Enrolls desiredPassword, which may be derived from a user selected pin
+ * or password, with the private key used only for enrolling authentication
+ * factor data.
+ *
+ * If there was already a password enrolled, current password handle must be
+ * passed in currentPasswordHandle, and current password must be passed in
+ * currentPassword. Valid currentPassword must verify() against
+ * currentPasswordHandle.
+ *
+ * @param uid The Android user identifier
+ *
+ * @param currentPasswordHandle The currently enrolled password handle the user
+ *    wants to replace. May be empty only if there's no currently enrolled
+ *    password. Otherwise must be non-empty.
+ *
+ * @param currentPassword The user's current password in plain text.
+ *    it MUST verify against current_password_handle if the latter is not-empty
+ *
+ * @param desiredPassword The new password the user wishes to enroll in
+ *    plaintext.
+ *
+ * @return response
+ *    On success, data buffer must contain the new password handle referencing
+ *    the password provided in desiredPassword.
+ *    This buffer can be used on subsequent calls to enroll or
+ *    verify. On error, this buffer must be empty.
+ *    response.code must always contain operation completion status.
+ *    This method may return ERROR_GENERAL_FAILURE or ERROR_RETRY_TIMEOUT on
+ *    failure. It must return STATUS_OK on success.
+ *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+ */
+enroll(uint32_t uid,
+       vec<uint8_t> currentPasswordHandle,
+       vec<uint8_t> currentPassword,
+       vec<uint8_t> desiredPassword)
+    generates (GatekeeperResponse response);
+
+/**
+ * Verifies that providedPassword matches enrolledPasswordHandle.
+ *
+ * Implementations of this module may retain the result of this call
+ * to attest to the recency of authentication.
+ *
+ * On success, returns verification token in response.data, which shall be
+ * usable to attest password verification to other trusted services.
+ *
+ * @param uid The Android user identifier
+ *
+ * @param challenge An optional challenge to authenticate against, or 0.
+ *    Used when a separate authenticator requests password verification,
+ *    or for transactional password authentication.
+ *
+ * @param enrolledPasswordHandle The currently enrolled password handle that
+ *    user wishes to verify against. Must be non-empty.
+ *
+ * @param providedPassword The plaintext password to be verified against the
+ *    enrolledPasswordHandle
+ *
+ * @return response
+ *    On success, a non-empty data buffer containing the
+ *    authentication token resulting from this verification is returned.
+ *    On error, data buffer must be empty.
+ *    response.code must always contain operation completion status.
+ *    This method may return ERROR_GENERAL_FAILURE or ERROR_RETRY_TIMEOUT on
+ *    failure. It must return STATUS_OK on success.
+ *    If password re-enrollment is necessary, it must return STATUS_REENROLL.
+ *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+ */
+verify(uint32_t uid, uint64_t challenge,
+       vec<uint8_t> enrolledPasswordHandle,
+       vec<uint8_t> providedPassword)
+    generates (GatekeeperResponse response);
+
+/*
+ * Deletes the enrolledPasswordHandle associated with the uid. Once deleted
+ * the user cannot be verified anymore.
+ * This is an optional method.
+ *
+ * @param uid The Android user identifier
+ *
+ * @return response
+ *    response.code must always contain operation completion status.
+ *    This method may return ERROR_GENERAL_FAILURE or ERROR_RETRY_TIMEOUT on
+ *    failure. It must return STATUS_OK on success.
+ *    If not implemented, it must return ERROR_NOT_IMPLEMENTED.
+ *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+ */
+deleteUser(uint32_t uid) generates (GatekeeperResponse response);
+
+/*
+ * Deletes all the enrolled_password_handles for all uid's. Once called,
+ * no users must be enrolled on the device.
+ * This is an optional method.
+ *
+ * @return response
+ *    response.code must always contain operation completion status.
+ *    This method may return ERROR_GENERAL_FAILURE or ERROR_RETRY_TIMEOUT on
+ *    failure. It must return STATUS_OK on success.
+ *    If not implemented, it must return ERROR_NOT_IMPLEMENTED.
+ *    If ERROR_RETRY_TIMEOUT is returned, response.timeout must be non-zero.
+ */
+deleteAllUsers() generates (GatekeeperResponse response);
+};
diff --git a/gatekeeper/1.0/default/Android.mk b/gatekeeper/1.0/default/Android.mk
new file mode 100644
index 0000000..e3b7d10
--- /dev/null
+++ b/gatekeeper/1.0/default/Android.mk
@@ -0,0 +1,40 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.gatekeeper@1.0-impl
+
+LOCAL_SRC_FILES := \
+    Gatekeeper.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.gatekeeper@1.0 \
+    libhardware \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog \
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.gatekeeper@1.0-service
+LOCAL_INIT_RC := android.hardware.gatekeeper@1.0-service.rc
+
+LOCAL_SRC_FILES := \
+    service.cpp    \
+
+LOCAL_SHARED_LIBRARIES := \
+    android.hardware.gatekeeper@1.0 \
+    libhardware \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog \
+
+include $(BUILD_EXECUTABLE)
diff --git a/gatekeeper/1.0/default/Gatekeeper.cpp b/gatekeeper/1.0/default/Gatekeeper.cpp
new file mode 100644
index 0000000..dce06e6
--- /dev/null
+++ b/gatekeeper/1.0/default/Gatekeeper.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.gatekeeper@1.0-service"
+
+#include <dlfcn.h>
+
+#include <log/log.h>
+
+#include "Gatekeeper.h"
+
+namespace android {
+namespace hardware {
+namespace gatekeeper {
+namespace V1_0 {
+namespace implementation {
+
+Gatekeeper::Gatekeeper()
+{
+    int ret = hw_get_module_by_class(GATEKEEPER_HARDWARE_MODULE_ID, NULL, &module);
+    device = NULL;
+
+    if (!ret) {
+        ret = gatekeeper_open(module, &device);
+    }
+    if (ret < 0) {
+        LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
+    }
+}
+
+Gatekeeper::~Gatekeeper()
+{
+    if (device != nullptr) {
+        int ret = gatekeeper_close(device);
+        if (ret < 0) {
+            ALOGE("Unable to close GateKeeper HAL");
+        }
+    }
+    dlclose(module->dso);
+}
+
+// Methods from ::android::hardware::gatekeeper::V1_0::IGatekeeper follow.
+Return<void> Gatekeeper::enroll(uint32_t uid,
+        const hidl_vec<uint8_t>& currentPasswordHandle,
+        const hidl_vec<uint8_t>& currentPassword,
+        const hidl_vec<uint8_t>& desiredPassword,
+        enroll_cb cb)
+{
+    GatekeeperResponse rsp;
+    uint8_t *enrolled_password_handle = nullptr;
+    uint32_t enrolled_password_handle_length = 0;
+
+    int ret = device->enroll(device, uid,
+            currentPasswordHandle.data(), currentPasswordHandle.size(),
+            currentPassword.data(), currentPassword.size(),
+            desiredPassword.data(), desiredPassword.size(),
+            &enrolled_password_handle, &enrolled_password_handle_length);
+    if (!ret) {
+        rsp.data.setToExternal(enrolled_password_handle,
+                               enrolled_password_handle_length,
+                               true);
+        rsp.code = GatekeeperStatusCode::STATUS_OK;
+    } else if (ret > 0) {
+        rsp.timeout = ret;
+        rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
+    } else {
+        rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
+    }
+    cb(rsp);
+    return Void();
+}
+
+Return<void> Gatekeeper::verify(uint32_t uid,
+                                uint64_t challenge,
+                                const hidl_vec<uint8_t>& enrolledPasswordHandle,
+                                const hidl_vec<uint8_t>& providedPassword,
+                                verify_cb cb)
+{
+    GatekeeperResponse rsp;
+    uint8_t *auth_token = nullptr;
+    uint32_t auth_token_length = 0;
+    bool request_reenroll = false;
+
+    int ret = device->verify(device, uid, challenge,
+            enrolledPasswordHandle.data(), enrolledPasswordHandle.size(),
+            providedPassword.data(), providedPassword.size(),
+            &auth_token, &auth_token_length,
+            &request_reenroll);
+    if (!ret) {
+        rsp.data.setToExternal(auth_token, auth_token_length, true);
+        if (request_reenroll) {
+            rsp.code = GatekeeperStatusCode::STATUS_REENROLL;
+        } else {
+            rsp.code = GatekeeperStatusCode::STATUS_OK;
+        }
+    } else if (ret > 0) {
+        rsp.timeout = ret;
+        rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
+    } else {
+        rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
+    }
+    cb(rsp);
+    return Void();
+}
+
+Return<void> Gatekeeper::deleteUser(uint32_t uid, deleteUser_cb cb)  {
+    GatekeeperResponse rsp;
+
+    if (device->delete_user != nullptr) {
+        int ret = device->delete_user(device, uid);
+        if (!ret) {
+            rsp.code = GatekeeperStatusCode::STATUS_OK;
+        } else if (ret > 0) {
+            rsp.timeout = ret;
+            rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
+        } else {
+            rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
+        }
+    } else {
+        rsp.code = GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED;
+    }
+    cb(rsp);
+    return Void();
+}
+
+Return<void> Gatekeeper::deleteAllUsers(deleteAllUsers_cb cb)  {
+    GatekeeperResponse rsp;
+    if (device->delete_all_users != nullptr) {
+        int ret = device->delete_all_users(device);
+        if (!ret) {
+            rsp.code = GatekeeperStatusCode::STATUS_OK;
+        } else if (ret > 0) {
+            rsp.timeout = ret;
+            rsp.code = GatekeeperStatusCode::ERROR_RETRY_TIMEOUT;
+        } else {
+            rsp.code = GatekeeperStatusCode::ERROR_GENERAL_FAILURE;
+        }
+    } else {
+        rsp.code = GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED;
+    }
+    cb(rsp);
+    return Void();
+}
+
+IGatekeeper* HIDL_FETCH_IGatekeeper(const char* /* name */) {
+    return new Gatekeeper();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace gatekeeper
+}  // namespace hardware
+}  // namespace android
diff --git a/gatekeeper/1.0/default/Gatekeeper.h b/gatekeeper/1.0/default/Gatekeeper.h
new file mode 100644
index 0000000..4cc01f6
--- /dev/null
+++ b/gatekeeper/1.0/default/Gatekeeper.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_GATEKEEPER_V1_0_GATEKEEPER_H
+#define ANDROID_HARDWARE_GATEKEEPER_V1_0_GATEKEEPER_H
+
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gatekeeper.h>
+
+namespace android {
+namespace hardware {
+namespace gatekeeper {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
+using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class Gatekeeper : public IGatekeeper {
+public:
+    Gatekeeper();
+    ~Gatekeeper();
+
+    // Methods from ::android::hardware::gatekeeper::V1_0::IGatekeeper follow.
+    Return<void> enroll(uint32_t uid,
+                        const hidl_vec<uint8_t>& currentPasswordHandle,
+                        const hidl_vec<uint8_t>& currentPassword,
+                        const hidl_vec<uint8_t>& desiredPassword,
+                        enroll_cb _hidl_cb)  override;
+    Return<void> verify(uint32_t uid,
+                        uint64_t challenge,
+                        const hidl_vec<uint8_t>& enrolledPasswordHandle,
+                        const hidl_vec<uint8_t>& providedPassword,
+                        verify_cb _hidl_cb)  override;
+    Return<void> deleteUser(uint32_t uid, deleteUser_cb _hidl_cb)  override;
+    Return<void> deleteAllUsers(deleteAllUsers_cb _hidl_cb)  override;
+private:
+    gatekeeper_device_t *device;
+    const hw_module_t *module;
+};
+
+extern "C" IGatekeeper* HIDL_FETCH_IGatekeeper(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gatekeeper
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GATEKEEPER_V1_0_GATEKEEPER_H
diff --git a/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
new file mode 100644
index 0000000..ac15e23
--- /dev/null
+++ b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
@@ -0,0 +1,4 @@
+service gatekeeper-1-0 /system/bin/hw/android.hardware.gatekeeper@1.0-service
+    class hal
+    user system
+    group system
diff --git a/gatekeeper/1.0/default/service.cpp b/gatekeeper/1.0/default/service.cpp
new file mode 100644
index 0000000..407cf71
--- /dev/null
+++ b/gatekeeper/1.0/default/service.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.gatekeeper@1.0-service"
+
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+
+#include <hidl/LegacySupport.h>
+
+// Generated HIDL files
+using android::hardware::gatekeeper::V1_0::IGatekeeper;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IGatekeeper>("gatekeeper");
+}
diff --git a/gatekeeper/1.0/types.hal b/gatekeeper/1.0/types.hal
new file mode 100644
index 0000000..8c184ee
--- /dev/null
+++ b/gatekeeper/1.0/types.hal
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+package android.hardware.gatekeeper@1.0;
+
+/**
+ * Gatekeeper response codes; success >= 0; error < 0
+ */
+enum GatekeeperStatusCode : int32_t {
+  STATUS_REENROLL       =  1,  // success, but upper layers should re-enroll
+                               // the verified password due to a version change
+  STATUS_OK             =  0,  // operation is successful
+  ERROR_GENERAL_FAILURE = -1,  // operation failed
+  ERROR_RETRY_TIMEOUT   = -2,  // operation should be retried after timeout
+  ERROR_NOT_IMPLEMENTED = -3,  // operation is not implemented
+};
+
+/**
+ * Gatekeeper response to any/all requests has this structure as mandatory part
+ */
+struct GatekeeperResponse {
+    /* request completion status */
+    GatekeeperStatusCode code;
+    /* retry timeout in ms, if code == ERROR_RETRY_TIMEOUT
+     * otherwise unused (0)
+     */
+    uint32_t timeout;
+    /* optional crypto blob */
+    vec<uint8_t> data;
+};
diff --git a/gatekeeper/1.0/vts/Gatekeeper.vts b/gatekeeper/1.0/vts/Gatekeeper.vts
new file mode 100644
index 0000000..25dc32f
--- /dev/null
+++ b/gatekeeper/1.0/vts/Gatekeeper.vts
@@ -0,0 +1,93 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IGatekeeper"
+
+package: "android.hardware.gatekeeper"
+
+import: "android.hardware.gatekeeper@1.0::types"
+
+interface: {
+    api: {
+        name: "enroll"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::gatekeeper::V1_0::GatekeeperResponse"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "verify"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::gatekeeper::V1_0::GatekeeperResponse"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "deleteUser"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::gatekeeper::V1_0::GatekeeperResponse"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "deleteAllUsers"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::gatekeeper::V1_0::GatekeeperResponse"
+        }
+    }
+
+}
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..9c72b81
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/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_test {
+    name: "gatekeeper_hidl_hal_test",
+    gtest: true,
+    srcs: ["gatekeeper_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.gatekeeper@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp b/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp
new file mode 100644
index 0000000..09690f8
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/gatekeeper_hidl_hal_test.cpp
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "gatekeeper_hidl_hal_test"
+
+#include <algorithm>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <hardware/hw_auth_token.h>
+
+#include <android/log.h>
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <android/hardware/gatekeeper/1.0/types.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::gatekeeper::V1_0::IGatekeeper;
+using ::android::hardware::gatekeeper::V1_0::GatekeeperResponse;
+using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+struct GatekeeperRequest {
+  uint32_t uid;
+  uint64_t challenge;
+  hidl_vec<uint8_t> curPwdHandle;
+  hidl_vec<uint8_t> curPwd;
+  hidl_vec<uint8_t> newPwd;
+  GatekeeperRequest() : uid(0), challenge(0) {}
+};
+
+// ASSERT_* macros generate return "void" internally
+// we have to use EXPECT_* if we return anything but "void"
+static const hw_auth_token_t *toAuthToken(GatekeeperResponse &rsp) {
+  const hw_auth_token_t *auth_token =
+      reinterpret_cast<hw_auth_token_t *>(rsp.data.data());
+  const size_t auth_token_size = rsp.data.size();
+
+  EXPECT_NE(nullptr, auth_token);
+  EXPECT_EQ(sizeof(hw_auth_token_t), auth_token_size);
+
+  if (auth_token != nullptr && auth_token_size >= sizeof(*auth_token)) {
+    // these are in network order: translate to host
+    uint32_t auth_type = ntohl(auth_token->authenticator_type);
+    uint64_t auth_tstamp = ntohq(auth_token->timestamp);
+
+    EXPECT_EQ(HW_AUTH_PASSWORD, auth_type);
+    EXPECT_NE(UINT64_C(~0), auth_tstamp);
+    EXPECT_EQ(HW_AUTH_TOKEN_VERSION, auth_token->version);
+    //        EXPECT_NE(UINT64_C(0), auth_token->authenticator_id);
+    ALOGI("Authenticator ID: %016" PRIX64, auth_token->authenticator_id);
+    EXPECT_NE(UINT32_C(0), auth_token->user_id);
+  }
+  return auth_token;
+}
+
+// The main test class for Gatekeeper HIDL HAL.
+class GatekeeperHidlTest : public ::testing::Test {
+ protected:
+  void setUid(uint32_t uid) { uid_ = uid; }
+
+  void doEnroll(GatekeeperRequest &req, GatekeeperResponse &rsp) {
+    while (true) {
+      auto ret = gatekeeper_->enroll(
+          uid_, req.curPwdHandle, req.curPwd, req.newPwd,
+          [&rsp](const GatekeeperResponse &cbRsp) { rsp = cbRsp; });
+      ASSERT_TRUE(ret.isOk());
+      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
+      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+      sleep(1);
+    }
+  }
+
+  void doVerify(GatekeeperRequest &req, GatekeeperResponse &rsp) {
+    while (true) {
+      auto ret = gatekeeper_->verify(
+          uid_, req.challenge, req.curPwdHandle, req.newPwd,
+          [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
+      ASSERT_TRUE(ret.isOk());
+      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
+      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+      sleep(1);
+    }
+  }
+
+  void doDeleteUser(GatekeeperResponse &rsp) {
+    while (true) {
+      auto ret = gatekeeper_->deleteUser(
+          uid_, [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
+      ASSERT_TRUE(ret.isOk());
+      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
+      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+      sleep(1);
+    }
+  }
+
+  void doDeleteAllUsers(GatekeeperResponse &rsp) {
+    while (true) {
+      auto ret = gatekeeper_->deleteAllUsers(
+          [&rsp](const GatekeeperResponse &cb_rsp) { rsp = cb_rsp; });
+      ASSERT_TRUE(ret.isOk());
+      if (rsp.code != GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) break;
+      ALOGI("%s: got retry code; retrying in 1 sec", __func__);
+      sleep(1);
+    }
+  }
+
+  void generatePassword(hidl_vec<uint8_t> &password, uint8_t seed) {
+    password.resize(16);
+    memset(password.data(), seed, password.size());
+  }
+
+  void checkEnroll(GatekeeperResponse &rsp, bool expectSuccess) {
+    if (expectSuccess) {
+      EXPECT_EQ(GatekeeperStatusCode::STATUS_OK, rsp.code);
+      EXPECT_NE(nullptr, rsp.data.data());
+      EXPECT_GT(rsp.data.size(), UINT32_C(0));
+    } else {
+      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
+      EXPECT_EQ(UINT32_C(0), rsp.data.size());
+    }
+  }
+
+  void checkVerify(GatekeeperResponse &rsp, uint64_t challenge,
+                   bool expectSuccess) {
+    if (expectSuccess) {
+      EXPECT_GE(rsp.code, GatekeeperStatusCode::STATUS_OK);
+      EXPECT_LE(rsp.code, GatekeeperStatusCode::STATUS_REENROLL);
+
+      const hw_auth_token_t *auth_token = toAuthToken(rsp);
+      ASSERT_NE(nullptr, auth_token);
+      EXPECT_EQ(challenge, auth_token->challenge);
+    } else {
+      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, rsp.code);
+      EXPECT_EQ(UINT32_C(0), rsp.data.size());
+    }
+  }
+
+  void enrollNewPassword(hidl_vec<uint8_t> &password, GatekeeperResponse &rsp,
+                         bool expectSuccess) {
+    GatekeeperRequest req;
+    req.newPwd.setToExternal(password.data(), password.size());
+    doEnroll(req, rsp);
+    checkEnroll(rsp, expectSuccess);
+  }
+
+  void verifyPassword(hidl_vec<uint8_t> &password,
+                      hidl_vec<uint8_t> &passwordHandle, uint64_t challenge,
+                      GatekeeperResponse &verifyRsp, bool expectSuccess) {
+    GatekeeperRequest verifyReq;
+
+    // build verify request for the same password (we want it to succeed)
+    verifyReq.newPwd = password;
+    // use enrolled password handle we've got
+    verifyReq.curPwdHandle = passwordHandle;
+    verifyReq.challenge = challenge;
+    doVerify(verifyReq, verifyRsp);
+    checkVerify(verifyRsp, challenge, expectSuccess);
+  }
+
+ protected:
+  sp<IGatekeeper> gatekeeper_;
+  uint32_t uid_;
+
+ public:
+  GatekeeperHidlTest() : uid_(0) {}
+  virtual void SetUp() override {
+    GatekeeperResponse rsp;
+    gatekeeper_ = IGatekeeper::getService("gatekeeper", false);
+    ASSERT_NE(nullptr, gatekeeper_.get());
+    doDeleteAllUsers(rsp);
+  }
+
+  virtual void TearDown() override {
+    GatekeeperResponse rsp;
+    doDeleteAllUsers(rsp);
+  }
+};
+
+/**
+ * Ensure we can enroll new password
+ */
+TEST_F(GatekeeperHidlTest, EnrollSuccess) {
+  hidl_vec<uint8_t> password;
+  GatekeeperResponse rsp;
+  ALOGI("Testing Enroll (expected success)");
+  generatePassword(password, 0);
+  enrollNewPassword(password, rsp, true);
+  ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can not enroll empty password
+ */
+TEST_F(GatekeeperHidlTest, EnrollNoPassword) {
+  hidl_vec<uint8_t> password;
+  GatekeeperResponse rsp;
+  ALOGI("Testing Enroll (expected failure)");
+  enrollNewPassword(password, rsp, false);
+  ALOGI("Testing Enroll done");
+}
+
+/**
+ * Ensure we can successfully verify previously enrolled password
+ */
+TEST_F(GatekeeperHidlTest, VerifySuccess) {
+  GatekeeperResponse enrollRsp;
+  GatekeeperResponse verifyRsp;
+  hidl_vec<uint8_t> password;
+
+  ALOGI("Testing Enroll+Verify (expected success)");
+  generatePassword(password, 0);
+  enrollNewPassword(password, enrollRsp, true);
+  verifyPassword(password, enrollRsp.data, 1, verifyRsp, true);
+  ALOGI("Testing Enroll+Verify done");
+}
+
+/**
+ * Ensure we can securely update password (keep the same
+ * secure user_id) if we prove we know old password
+ */
+TEST_F(GatekeeperHidlTest, TrustedReenroll) {
+  GatekeeperResponse enrollRsp;
+  GatekeeperRequest reenrollReq;
+  GatekeeperResponse reenrollRsp;
+  GatekeeperResponse verifyRsp;
+  GatekeeperResponse reenrollVerifyRsp;
+  hidl_vec<uint8_t> password;
+  hidl_vec<uint8_t> newPassword;
+
+  generatePassword(password, 0);
+
+  ALOGI("Testing Trusted Reenroll (expected success)");
+  enrollNewPassword(password, enrollRsp, true);
+  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+  ALOGI("Primary Enroll+Verify done");
+
+  generatePassword(newPassword, 1);
+  reenrollReq.newPwd.setToExternal(newPassword.data(), newPassword.size());
+  reenrollReq.curPwd.setToExternal(password.data(), password.size());
+  reenrollReq.curPwdHandle.setToExternal(enrollRsp.data.data(),
+                                         enrollRsp.data.size());
+
+  doEnroll(reenrollReq, reenrollRsp);
+  checkEnroll(reenrollRsp, true);
+  verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+  ALOGI("Trusted ReEnroll+Verify done");
+
+  const hw_auth_token_t *first = toAuthToken(verifyRsp);
+  const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
+  if (first != nullptr && second != nullptr) {
+    EXPECT_EQ(first->user_id, second->user_id);
+  }
+  ALOGI("Testing Trusted Reenroll done");
+}
+
+/**
+ * Ensure we can update password (and get new
+ * secure user_id) if we don't know old password
+ */
+TEST_F(GatekeeperHidlTest, UntrustedReenroll) {
+  GatekeeperResponse enrollRsp;
+  GatekeeperRequest reenrollReq;
+  GatekeeperResponse reenrollRsp;
+  GatekeeperResponse verifyRsp;
+  GatekeeperResponse reenrollVerifyRsp;
+  hidl_vec<uint8_t> password;
+  hidl_vec<uint8_t> newPassword;
+
+  ALOGI("Testing Untrusted Reenroll (expected success)");
+  generatePassword(password, 0);
+  enrollNewPassword(password, enrollRsp, true);
+  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+  ALOGI("Primary Enroll+Verify done");
+
+  generatePassword(newPassword, 1);
+  enrollNewPassword(newPassword, reenrollRsp, true);
+  verifyPassword(newPassword, reenrollRsp.data, 0, reenrollVerifyRsp, true);
+  ALOGI("Untrusted ReEnroll+Verify done");
+
+  const hw_auth_token_t *first = toAuthToken(verifyRsp);
+  const hw_auth_token_t *second = toAuthToken(reenrollVerifyRsp);
+  if (first != nullptr && second != nullptr) {
+    EXPECT_NE(first->user_id, second->user_id);
+  }
+  ALOGI("Testing Untrusted Reenroll done");
+}
+
+/**
+ * Ensure we dont get successful verify with invalid data
+ */
+TEST_F(GatekeeperHidlTest, VerifyNoData) {
+  hidl_vec<uint8_t> password;
+  hidl_vec<uint8_t> passwordHandle;
+  GatekeeperResponse verifyRsp;
+
+  ALOGI("Testing Verify (expected failure)");
+  verifyPassword(password, passwordHandle, 0, verifyRsp, false);
+  EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
+  ALOGI("Testing Verify done");
+}
+
+/**
+ * Ensure we can not verify password after we enrolled it and then deleted user
+ */
+TEST_F(GatekeeperHidlTest, DeleteUserTest) {
+  hidl_vec<uint8_t> password;
+  GatekeeperResponse enrollRsp;
+  GatekeeperResponse verifyRsp;
+  GatekeeperResponse delRsp;
+  ALOGI("Testing deleteUser (expected success)");
+  setUid(10001);
+  generatePassword(password, 0);
+  enrollNewPassword(password, enrollRsp, true);
+  verifyPassword(password, enrollRsp.data, 0, verifyRsp, true);
+  ALOGI("Enroll+Verify done");
+  doDeleteUser(delRsp);
+  EXPECT_EQ(UINT32_C(0), delRsp.data.size());
+  EXPECT_TRUE(delRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
+              delRsp.code == GatekeeperStatusCode::STATUS_OK);
+  ALOGI("DeleteUser done");
+  if (delRsp.code == GatekeeperStatusCode::STATUS_OK) {
+    verifyPassword(password, enrollRsp.data, 0, verifyRsp, false);
+    EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE, verifyRsp.code);
+    ALOGI("Verify after Delete done (must fail)");
+  }
+  ALOGI("Testing deleteUser done: rsp=%" PRIi32, delRsp.code);
+}
+
+/**
+ * Ensure we can not verify passwords after we enrolled them and then deleted
+ * all users
+ */
+TEST_F(GatekeeperHidlTest, DeleteAllUsersTest) {
+  struct UserData {
+    uint32_t userId;
+    hidl_vec<uint8_t> password;
+    GatekeeperResponse enrollRsp;
+    GatekeeperResponse verifyRsp;
+    UserData(int id) { userId = id; }
+  } users[3]{10001, 10002, 10003};
+  GatekeeperResponse delAllRsp;
+  ALOGI("Testing deleteAllUsers (expected success)");
+
+  // enroll multiple users
+  for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+    setUid(users[i].userId);
+    generatePassword(users[i].password, (i % 255) + 1);
+    enrollNewPassword(users[i].password, users[i].enrollRsp, true);
+  }
+  ALOGI("Multiple users enrolled");
+
+  // verify multiple users
+  for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+    setUid(users[i].userId);
+    verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
+                   users[i].verifyRsp, true);
+  }
+  ALOGI("Multiple users verified");
+
+  doDeleteAllUsers(delAllRsp);
+  EXPECT_EQ(UINT32_C(0), delAllRsp.data.size());
+  EXPECT_TRUE(delAllRsp.code == GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED ||
+              delAllRsp.code == GatekeeperStatusCode::STATUS_OK);
+  ALOGI("All users deleted");
+
+  if (delAllRsp.code == GatekeeperStatusCode::STATUS_OK) {
+    // verify multiple users after they are deleted; all must fail
+    for (size_t i = 0; i < sizeof(users) / sizeof(users[0]); ++i) {
+      setUid(users[i].userId);
+      verifyPassword(users[i].password, users[i].enrollRsp.data, 0,
+                     users[i].verifyRsp, false);
+      EXPECT_EQ(GatekeeperStatusCode::ERROR_GENERAL_FAILURE,
+                users[i].verifyRsp.code);
+    }
+    ALOGI("Multiple users verified after delete (all must fail)");
+  }
+
+  ALOGI("Testing deleteAllUsers done: rsp=%" PRIi32, delAllRsp.code);
+}
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/__init__.py b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/__init__.py
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/__init__.py b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/__init__.py
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/Android.mk b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/Android.mk
new file mode 100644
index 0000000..59bfe17
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalGatekeeperHidlTargetBasicTest
+VTS_CONFIG_SRC_DIR := testcases/hal/gatekeeper/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/AndroidTest.xml b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..9256823
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Gatekeeper HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalGatekeeperHidlTargetBasicTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/gatekeeper_hidl_hal_test/gatekeeper_hidl_hal_test,
+            _64bit::DATA/nativetest64/gatekeeper_hidl_hal_test/gatekeeper_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/Android.mk b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..384b33c
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalGatekeeperHidlTargetBasicProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/gatekeeper/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/AndroidTest.xml b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..18bb442
--- /dev/null
+++ b/gatekeeper/1.0/vts/functional/vts/testcases/hal/gatekeeper/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Gatekeeper HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalGatekeeperHidlTargetBasicProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/gatekeeper_hidl_hal_test/gatekeeper_hidl_hal_test,
+            _64bit::DATA/nativetest64/gatekeeper_hidl_hal_test/gatekeeper_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/gatekeeper/1.0/vts/types.vts b/gatekeeper/1.0/vts/types.vts
new file mode 100644
index 0000000..3de9a14
--- /dev/null
+++ b/gatekeeper/1.0/vts/types.vts
@@ -0,0 +1,59 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.gatekeeper"
+
+
+attribute: {
+    name: "::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STATUS_REENROLL"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "STATUS_OK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ERROR_GENERAL_FAILURE"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "ERROR_RETRY_TIMEOUT"
+        scalar_value: {
+            int32_t: -2
+        }
+        enumerator: "ERROR_NOT_IMPLEMENTED"
+        scalar_value: {
+            int32_t: -3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::gatekeeper::V1_0::GatekeeperResponse"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "code"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode"
+    }
+    struct_value: {
+        name: "timeout"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "data"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
diff --git a/gatekeeper/Android.bp b/gatekeeper/Android.bp
new file mode 100644
index 0000000..33f70eb
--- /dev/null
+++ b/gatekeeper/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/vts/functional",
+]
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
new file mode 100644
index 0000000..4d7e26e
--- /dev/null
+++ b/gnss/1.0/Android.bp
@@ -0,0 +1,208 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.gnss@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.gnss@1.0",
+    srcs: [
+        "types.hal",
+        "IAGnss.hal",
+        "IAGnssCallback.hal",
+        "IAGnssRil.hal",
+        "IAGnssRilCallback.hal",
+        "IGnss.hal",
+        "IGnssBatching.hal",
+        "IGnssBatchingCallback.hal",
+        "IGnssCallback.hal",
+        "IGnssConfiguration.hal",
+        "IGnssDebug.hal",
+        "IGnssGeofenceCallback.hal",
+        "IGnssGeofencing.hal",
+        "IGnssMeasurement.hal",
+        "IGnssMeasurementCallback.hal",
+        "IGnssNavigationMessage.hal",
+        "IGnssNavigationMessageCallback.hal",
+        "IGnssNi.hal",
+        "IGnssNiCallback.hal",
+        "IGnssXtra.hal",
+        "IGnssXtraCallback.hal",
+    ],
+    out: [
+        "android/hardware/gnss/1.0/types.cpp",
+        "android/hardware/gnss/1.0/AGnssAll.cpp",
+        "android/hardware/gnss/1.0/AGnssCallbackAll.cpp",
+        "android/hardware/gnss/1.0/AGnssRilAll.cpp",
+        "android/hardware/gnss/1.0/AGnssRilCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssAll.cpp",
+        "android/hardware/gnss/1.0/GnssBatchingAll.cpp",
+        "android/hardware/gnss/1.0/GnssBatchingCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssConfigurationAll.cpp",
+        "android/hardware/gnss/1.0/GnssDebugAll.cpp",
+        "android/hardware/gnss/1.0/GnssGeofenceCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssGeofencingAll.cpp",
+        "android/hardware/gnss/1.0/GnssMeasurementAll.cpp",
+        "android/hardware/gnss/1.0/GnssMeasurementCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssNavigationMessageAll.cpp",
+        "android/hardware/gnss/1.0/GnssNavigationMessageCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssNiAll.cpp",
+        "android/hardware/gnss/1.0/GnssNiCallbackAll.cpp",
+        "android/hardware/gnss/1.0/GnssXtraAll.cpp",
+        "android/hardware/gnss/1.0/GnssXtraCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.gnss@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.gnss@1.0",
+    srcs: [
+        "types.hal",
+        "IAGnss.hal",
+        "IAGnssCallback.hal",
+        "IAGnssRil.hal",
+        "IAGnssRilCallback.hal",
+        "IGnss.hal",
+        "IGnssBatching.hal",
+        "IGnssBatchingCallback.hal",
+        "IGnssCallback.hal",
+        "IGnssConfiguration.hal",
+        "IGnssDebug.hal",
+        "IGnssGeofenceCallback.hal",
+        "IGnssGeofencing.hal",
+        "IGnssMeasurement.hal",
+        "IGnssMeasurementCallback.hal",
+        "IGnssNavigationMessage.hal",
+        "IGnssNavigationMessageCallback.hal",
+        "IGnssNi.hal",
+        "IGnssNiCallback.hal",
+        "IGnssXtra.hal",
+        "IGnssXtraCallback.hal",
+    ],
+    out: [
+        "android/hardware/gnss/1.0/types.h",
+        "android/hardware/gnss/1.0/IAGnss.h",
+        "android/hardware/gnss/1.0/IHwAGnss.h",
+        "android/hardware/gnss/1.0/BnHwAGnss.h",
+        "android/hardware/gnss/1.0/BpHwAGnss.h",
+        "android/hardware/gnss/1.0/BsAGnss.h",
+        "android/hardware/gnss/1.0/IAGnssCallback.h",
+        "android/hardware/gnss/1.0/IHwAGnssCallback.h",
+        "android/hardware/gnss/1.0/BnHwAGnssCallback.h",
+        "android/hardware/gnss/1.0/BpHwAGnssCallback.h",
+        "android/hardware/gnss/1.0/BsAGnssCallback.h",
+        "android/hardware/gnss/1.0/IAGnssRil.h",
+        "android/hardware/gnss/1.0/IHwAGnssRil.h",
+        "android/hardware/gnss/1.0/BnHwAGnssRil.h",
+        "android/hardware/gnss/1.0/BpHwAGnssRil.h",
+        "android/hardware/gnss/1.0/BsAGnssRil.h",
+        "android/hardware/gnss/1.0/IAGnssRilCallback.h",
+        "android/hardware/gnss/1.0/IHwAGnssRilCallback.h",
+        "android/hardware/gnss/1.0/BnHwAGnssRilCallback.h",
+        "android/hardware/gnss/1.0/BpHwAGnssRilCallback.h",
+        "android/hardware/gnss/1.0/BsAGnssRilCallback.h",
+        "android/hardware/gnss/1.0/IGnss.h",
+        "android/hardware/gnss/1.0/IHwGnss.h",
+        "android/hardware/gnss/1.0/BnHwGnss.h",
+        "android/hardware/gnss/1.0/BpHwGnss.h",
+        "android/hardware/gnss/1.0/BsGnss.h",
+        "android/hardware/gnss/1.0/IGnssBatching.h",
+        "android/hardware/gnss/1.0/IHwGnssBatching.h",
+        "android/hardware/gnss/1.0/BnHwGnssBatching.h",
+        "android/hardware/gnss/1.0/BpHwGnssBatching.h",
+        "android/hardware/gnss/1.0/BsGnssBatching.h",
+        "android/hardware/gnss/1.0/IGnssBatchingCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssBatchingCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssBatchingCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssBatchingCallback.h",
+        "android/hardware/gnss/1.0/BsGnssBatchingCallback.h",
+        "android/hardware/gnss/1.0/IGnssCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssCallback.h",
+        "android/hardware/gnss/1.0/BsGnssCallback.h",
+        "android/hardware/gnss/1.0/IGnssConfiguration.h",
+        "android/hardware/gnss/1.0/IHwGnssConfiguration.h",
+        "android/hardware/gnss/1.0/BnHwGnssConfiguration.h",
+        "android/hardware/gnss/1.0/BpHwGnssConfiguration.h",
+        "android/hardware/gnss/1.0/BsGnssConfiguration.h",
+        "android/hardware/gnss/1.0/IGnssDebug.h",
+        "android/hardware/gnss/1.0/IHwGnssDebug.h",
+        "android/hardware/gnss/1.0/BnHwGnssDebug.h",
+        "android/hardware/gnss/1.0/BpHwGnssDebug.h",
+        "android/hardware/gnss/1.0/BsGnssDebug.h",
+        "android/hardware/gnss/1.0/IGnssGeofenceCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssGeofenceCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssGeofenceCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssGeofenceCallback.h",
+        "android/hardware/gnss/1.0/BsGnssGeofenceCallback.h",
+        "android/hardware/gnss/1.0/IGnssGeofencing.h",
+        "android/hardware/gnss/1.0/IHwGnssGeofencing.h",
+        "android/hardware/gnss/1.0/BnHwGnssGeofencing.h",
+        "android/hardware/gnss/1.0/BpHwGnssGeofencing.h",
+        "android/hardware/gnss/1.0/BsGnssGeofencing.h",
+        "android/hardware/gnss/1.0/IGnssMeasurement.h",
+        "android/hardware/gnss/1.0/IHwGnssMeasurement.h",
+        "android/hardware/gnss/1.0/BnHwGnssMeasurement.h",
+        "android/hardware/gnss/1.0/BpHwGnssMeasurement.h",
+        "android/hardware/gnss/1.0/BsGnssMeasurement.h",
+        "android/hardware/gnss/1.0/IGnssMeasurementCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssMeasurementCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssMeasurementCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssMeasurementCallback.h",
+        "android/hardware/gnss/1.0/BsGnssMeasurementCallback.h",
+        "android/hardware/gnss/1.0/IGnssNavigationMessage.h",
+        "android/hardware/gnss/1.0/IHwGnssNavigationMessage.h",
+        "android/hardware/gnss/1.0/BnHwGnssNavigationMessage.h",
+        "android/hardware/gnss/1.0/BpHwGnssNavigationMessage.h",
+        "android/hardware/gnss/1.0/BsGnssNavigationMessage.h",
+        "android/hardware/gnss/1.0/IGnssNavigationMessageCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssNavigationMessageCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssNavigationMessageCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssNavigationMessageCallback.h",
+        "android/hardware/gnss/1.0/BsGnssNavigationMessageCallback.h",
+        "android/hardware/gnss/1.0/IGnssNi.h",
+        "android/hardware/gnss/1.0/IHwGnssNi.h",
+        "android/hardware/gnss/1.0/BnHwGnssNi.h",
+        "android/hardware/gnss/1.0/BpHwGnssNi.h",
+        "android/hardware/gnss/1.0/BsGnssNi.h",
+        "android/hardware/gnss/1.0/IGnssNiCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssNiCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssNiCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssNiCallback.h",
+        "android/hardware/gnss/1.0/BsGnssNiCallback.h",
+        "android/hardware/gnss/1.0/IGnssXtra.h",
+        "android/hardware/gnss/1.0/IHwGnssXtra.h",
+        "android/hardware/gnss/1.0/BnHwGnssXtra.h",
+        "android/hardware/gnss/1.0/BpHwGnssXtra.h",
+        "android/hardware/gnss/1.0/BsGnssXtra.h",
+        "android/hardware/gnss/1.0/IGnssXtraCallback.h",
+        "android/hardware/gnss/1.0/IHwGnssXtraCallback.h",
+        "android/hardware/gnss/1.0/BnHwGnssXtraCallback.h",
+        "android/hardware/gnss/1.0/BpHwGnssXtraCallback.h",
+        "android/hardware/gnss/1.0/BsGnssXtraCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.gnss@1.0",
+    generated_sources: ["android.hardware.gnss@1.0_genc++"],
+    generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/gnss/1.0/Android.mk b/gnss/1.0/Android.mk
new file mode 100644
index 0000000..130c14e
--- /dev/null
+++ b/gnss/1.0/Android.mk
@@ -0,0 +1,1050 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (GnssConstellationType)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssConstellationType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssConstellationType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssLocation)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssLocation.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssLocation
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssLocationFlags)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssLocationFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssLocationFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssMax)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssMax.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssMax
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnss.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnss.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnss
+
+$(GEN): $(LOCAL_PATH)/IAGnss.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssCallback
+
+$(GEN): $(LOCAL_PATH)/IAGnssCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssRil.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssRil.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssRil
+
+$(GEN): $(LOCAL_PATH)/IAGnssRil.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssRilCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssRilCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssRilCallback
+
+$(GEN): $(LOCAL_PATH)/IAGnssRilCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnss.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnss.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnss.hal
+$(GEN): $(LOCAL_PATH)/IAGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnss
+
+$(GEN): $(LOCAL_PATH)/IGnss.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssBatching.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssBatching.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssBatching
+
+$(GEN): $(LOCAL_PATH)/IGnssBatching.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssBatchingCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssBatchingCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssBatchingCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssBatchingCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssConfiguration.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssConfiguration.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssConfiguration
+
+$(GEN): $(LOCAL_PATH)/IGnssConfiguration.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssDebug.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssDebug.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssDebug
+
+$(GEN): $(LOCAL_PATH)/IGnssDebug.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssGeofenceCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssGeofenceCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssGeofenceCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssGeofencing.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssGeofencing.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssGeofencing
+
+$(GEN): $(LOCAL_PATH)/IGnssGeofencing.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssMeasurement.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssMeasurement.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssMeasurement
+
+$(GEN): $(LOCAL_PATH)/IGnssMeasurement.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssMeasurementCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssMeasurementCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssMeasurementCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNavigationMessage.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNavigationMessage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNavigationMessage
+
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessage.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNavigationMessageCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNavigationMessageCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNi.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNi.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNi
+
+$(GEN): $(LOCAL_PATH)/IGnssNi.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNiCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNiCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNiCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssNiCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssXtra.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssXtra.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssXtra
+
+$(GEN): $(LOCAL_PATH)/IGnssXtra.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssXtraCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssXtraCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssXtraCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssXtraCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (GnssConstellationType)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssConstellationType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssConstellationType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssLocation)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssLocation.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssLocation
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssLocationFlags)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssLocationFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssLocationFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (GnssMax)
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/GnssMax.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::types.GnssMax
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnss.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnss.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnss
+
+$(GEN): $(LOCAL_PATH)/IAGnss.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssCallback
+
+$(GEN): $(LOCAL_PATH)/IAGnssCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssRil.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssRil.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssRil
+
+$(GEN): $(LOCAL_PATH)/IAGnssRil.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IAGnssRilCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IAGnssRilCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IAGnssRilCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IAGnssRilCallback
+
+$(GEN): $(LOCAL_PATH)/IAGnssRilCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnss.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnss.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnss.hal
+$(GEN): $(LOCAL_PATH)/IAGnss.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): $(LOCAL_PATH)/IAGnssRil.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnss
+
+$(GEN): $(LOCAL_PATH)/IGnss.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssBatching.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssBatching.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssBatching.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssBatching
+
+$(GEN): $(LOCAL_PATH)/IGnssBatching.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssBatchingCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssBatchingCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssBatchingCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssBatchingCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssBatchingCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssConfiguration.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssConfiguration.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssConfiguration.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssConfiguration
+
+$(GEN): $(LOCAL_PATH)/IGnssConfiguration.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssDebug.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssDebug.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssDebug.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssDebug
+
+$(GEN): $(LOCAL_PATH)/IGnssDebug.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssGeofenceCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssGeofenceCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssGeofenceCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssGeofencing.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssGeofencing.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssGeofencing.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssGeofenceCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssGeofencing
+
+$(GEN): $(LOCAL_PATH)/IGnssGeofencing.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssMeasurement.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssMeasurement.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssMeasurement.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssMeasurement
+
+$(GEN): $(LOCAL_PATH)/IGnssMeasurement.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssMeasurementCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssMeasurementCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssMeasurementCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssMeasurementCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNavigationMessage.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNavigationMessage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNavigationMessage.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNavigationMessage
+
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessage.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNavigationMessageCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNavigationMessageCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNavigationMessageCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssNavigationMessageCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNi.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNi.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNi.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNi
+
+$(GEN): $(LOCAL_PATH)/IGnssNi.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssNiCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssNiCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssNiCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssNiCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssNiCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssXtra.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssXtra.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssXtra.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssXtra
+
+$(GEN): $(LOCAL_PATH)/IGnssXtra.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IGnssXtraCallback.hal
+#
+GEN := $(intermediates)/android/hardware/gnss/V1_0/IGnssXtraCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IGnssXtraCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.gnss@1.0::IGnssXtraCallback
+
+$(GEN): $(LOCAL_PATH)/IGnssXtraCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/gnss/1.0/IAGnss.hal b/gnss/1.0/IAGnss.hal
new file mode 100644
index 0000000..b8f5746
--- /dev/null
+++ b/gnss/1.0/IAGnss.hal
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IAGnssCallback;
+
+/*
+ * Extended interface for AGNSS support.
+ */
+interface IAGnss {
+    @export(name="", value_prefix="APN_IP_")
+    enum ApnIpType : uint8_t {
+        INVALID  = 0,
+        IPV4     = 1,
+        IPV6     = 2,
+        IPV4V6   = 3
+    };
+
+    /*
+     * Opens the AGNSS interface and provides the callback routines to the
+     * implementation of this interface.
+     *
+     * @param callback Handle to the AGNSS status callback interface.
+     */
+    setCallback(IAGnssCallback callback);
+
+    /*
+     * Notifies that the AGNSS data connection has been closed.
+     *
+     * @return success True if the operation is successful.
+     */
+    dataConnClosed() generates (bool success);
+
+    /*
+     * Notifies that a data connection is not available for AGNSS.
+     *
+     * @return success True if the operation is successful.
+     */
+    dataConnFailed() generates (bool success);
+
+    /*
+     * Sets the hostname and port for the AGNSS server.
+     *
+     * @param type Specifies if SUPL or C2K.
+     * @param hostname Hostname of the AGNSS server.
+     * @param port Port number associated with the server.
+     *
+     * @return success True if the operation is successful.
+     */
+    setServer(AGnssType type, string hostname, int32_t port)
+        generates (bool success);
+
+    /*
+     * Notifies that a data connection is available and sets the name of the
+     * APN, and its IP type, to be used for SUPL connections.
+     *
+     * @param apn Access Point Name(follows regular APN naming convention).
+     * @param apnIpType Specifies if SUPL or C2K.
+     *
+     * @return success True if the operation is successful.
+     */
+    dataConnOpen(string apn, ApnIpType apnIpType)
+        generates (bool success);
+};
diff --git a/gnss/1.0/IAGnssCallback.hal b/gnss/1.0/IAGnssCallback.hal
new file mode 100644
index 0000000..fe2e101
--- /dev/null
+++ b/gnss/1.0/IAGnssCallback.hal
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss@1.0;
+
+/** Callback structure for the AGNSS interface. */
+interface IAGnssCallback {
+    /** AGNSS type **/
+    @export(name="", value_prefix="AGPS_")
+    enum AGnssType : uint8_t {
+        TYPE_SUPL         = 1,
+        TYPE_C2K          = 2
+    };
+
+    @export(name="", value_prefix="GNSS_")
+    enum AGnssStatusValue : uint8_t {
+        /** GNSS requests data connection for AGNSS. */
+        REQUEST_AGNSS_DATA_CONN  = 1,
+        /** GNSS releases the AGNSS data connection. */
+        RELEASE_AGNSS_DATA_CONN  = 2,
+        /** AGNSS data connection initiated */
+        AGNSS_DATA_CONNECTED     = 3,
+        /** AGNSS data connection completed */
+        AGNSS_DATA_CONN_DONE     = 4,
+        /** AGNSS data connection failed */
+        AGNSS_DATA_CONN_FAILED   = 5
+    };
+
+    /*
+     * Represents the status of AGNSS augmented to support IPv4.
+     */
+    @export(name="", value_prefix="GPS_")
+    struct AGnssStatusIpV4 {
+        AGnssType type;
+        AGnssStatusValue status;
+        /*
+         * 32-bit IPv4 address.
+         */
+        uint32_t ipV4Addr;
+    };
+
+    /*
+     * Represents the status of AGNSS augmented to support IPv6.
+     */
+    struct AGnssStatusIpV6 {
+        AGnssType type;
+        AGnssStatusValue status;
+        /*
+         * 128-bit IPv6 address.
+         */
+        uint8_t[16] ipV6Addr;
+    };
+
+    /*
+     * Callback with AGNSS(IpV4) status information.
+     *
+     * @param status Will be of type AGnssStatusIpV4.
+     */
+    agnssStatusIpV4Cb(AGnssStatusIpV4 status);
+
+    /*
+     * Callback with AGNSS(IpV6) status information.
+     *
+     * @param status Will be of type AGnssStatusIpV6.
+     */
+    agnssStatusIpV6Cb(AGnssStatusIpV6 status);
+
+};
diff --git a/gnss/1.0/IAGnssRil.hal b/gnss/1.0/IAGnssRil.hal
new file mode 100644
index 0000000..6292273
--- /dev/null
+++ b/gnss/1.0/IAGnssRil.hal
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IAGnssRilCallback;
+
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface
+ * Layer interface allows the GNSS chipset to request radio interface layer
+ * information from Android platform. Examples of such information are reference
+ * location, unique subscriber ID, phone number string and network availability changes.
+ */
+interface IAGnssRil {
+    @export(name="", value_prefix="AGPS_SETID_TYPE_")
+    enum SetIDType : uint8_t {
+        NONE    = 0,
+        IMSI    = 1,
+        MSISDM  = 2
+    };
+
+    @export(name="", value_prefix="AGPS_RIL_NETWORK_TYPE_")
+    enum NetworkType : uint8_t {
+        MOBILE  = 0,
+        WIFI    = 1,
+        MMS     = 2,
+        SUPL    = 3,
+        DUN     = 4,
+        HIPRI   = 5,
+        WIMAX   = 6,
+    };
+
+    @export(name="", value_prefix="AGPS_REF_LOCATION_TYPE_")
+    enum AGnssRefLocationType : uint8_t {
+        GSM_CELLID   = 1,
+        UMTS_CELLID  = 2,
+        LTE_CELLID   = 4,
+    };
+
+    /* CellID for 2G, 3G and LTE, used in AGNSS. */
+    struct AGnssRefLocationCellID {
+        AGnssRefLocationType type;
+
+        /* Mobile Country Code. */
+        uint16_t mcc;
+
+        /* Mobile Network Code .*/
+        uint16_t mnc;
+
+        /*
+         * Location Area Code in 2G, 3G and LTE. In 3G lac is discarded. In LTE,
+         * lac is populated with tac, to ensure that we don't break old clients that
+         * might rely in the old (wrong) behavior.
+         */
+        uint16_t lac;
+
+        /* Cell id in 2G. Utran Cell id in 3G. Cell Global Id EUTRA in LTE. */
+        uint32_t cid;
+
+        /* Tracking Area Code in LTE. */
+        uint16_t tac;
+
+        /* Physical Cell id in LTE (not used in 2G and 3G) */
+        uint16_t pcid;
+    };
+
+    /* Represents ref locations */
+    struct AGnssRefLocation {
+        AGnssRefLocationType type;
+
+        AGnssRefLocationCellID cellID;
+    };
+
+    /*
+     * Opens the AGNSS interface and provides the callback routines
+     * to the implementation of this interface.
+     *
+     * @param callback Interface for AGnssRil callbacks.
+     */
+    setCallback(IAGnssRilCallback callback);
+
+    /*
+     * Sets the reference location.
+     *
+     * @param agnssReflocation AGNSS reference location CellID.
+     */
+    setRefLocation(AGnssRefLocation agnssReflocation);
+
+    /*
+     * Sets the SET ID.
+     *
+     * @param type Must be populated with either IMSI or MSISDN or NONE.
+     * @param setid If type is IMSI then setid is populated with
+     * a string representing the unique Subscriber ID, for example, the IMSI for
+     * a GMS phone. If type is MSISDN, then setid must contain
+     * the phone number string for line 1. For example, the MSISDN for a GSM phone.
+     * If the type is NONE, then the string must be empty.
+     *
+     * @return success True if all parameters were valid and operation was
+     * successful.
+     */
+    setSetId(SetIDType type, string setid) generates (bool success);
+
+    /*
+     * Notify GNSS of network status changes.
+     *
+     * @param connected Indicates whether network connectivity exists and
+     * it is possible to establish connections and pass data.
+     * @param type Indicates the kind of network, for eg. mobile, wifi etc.
+     * @param roaming Indicates whether the device is currently roaming on
+     * this network.
+     *
+     * @return success True is all parameters were valid and operation was
+     * successful.
+     */
+    updateNetworkState(bool connected, NetworkType type, bool roaming)
+        generates (bool success);
+
+    /*
+     * Notify GNSS of network status changes.
+     *
+     * @param available Indicates whether network connectivity is available.
+     * @param apn String containing the Access Point Name.
+     *
+     * @return success True if all parameters were valid and the operation was
+     * successful.
+     * TODO(b/32022567): Add VTS test to validate the format of APN.
+     */
+    updateNetworkAvailability(bool available, string apn) generates (bool success);
+
+};
diff --git a/gnss/1.0/IAGnssRilCallback.hal b/gnss/1.0/IAGnssRilCallback.hal
new file mode 100644
index 0000000..2d64e54
--- /dev/null
+++ b/gnss/1.0/IAGnssRilCallback.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/*
+ * Callback for IAGnssRil interface. Used to request SET ID and
+ * Reference Location.
+ */
+interface IAGnssRilCallback {
+    /* Kinds of SET ID that can be requested */
+    @export(name="", value_prefix="AGPS_RIL_REQUEST_SETID_")
+    enum ID : uint32_t {
+        IMSI    = 1 << 0L,
+        MSISDN  = 1 << 1L,
+    };
+
+    /*
+     * The Hal uses this API to request a SET ID.
+     *
+     * @param setIdflag Specifies the kind of SET ID that is required by the HAL.
+     */
+    requestSetIdCb(bitfield<ID> setIdflag);
+
+    /*
+     * The Hal uses this API to request a reference location.
+     *
+     */
+    requestRefLocCb();
+
+};
diff --git a/gnss/1.0/IGnss.hal b/gnss/1.0/IGnss.hal
new file mode 100644
index 0000000..5cde79e
--- /dev/null
+++ b/gnss/1.0/IGnss.hal
@@ -0,0 +1,237 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IAGnss;
+import IAGnssRil;
+import IGnssBatching;
+import IGnssCallback;
+import IGnssConfiguration;
+import IGnssDebug;
+import IGnssMeasurement;
+import IGnssNavigationMessage;
+import IGnssGeofencing;
+import IGnssNi;
+import IGnssXtra;
+
+/* Represents the standard GNSS (Global Navigation Satellite System) interface. */
+interface IGnss {
+    /* Requested operational mode for GNSS operation. */
+    @export(name="", value_prefix="GPS_POSITION_MODE_")
+    enum GnssPositionMode : uint8_t {
+        /** Mode for running GNSS standalone (no assistance). */
+        STANDALONE  = 0,
+        /** AGNSS MS-Based mode. */
+        MS_BASED    = 1,
+        /*
+         * AGNSS MS-Assisted mode. This mode is not maintained by the platform anymore.
+         * It is strongly recommended to use MS_BASED instead.
+         */
+        MS_ASSISTED = 2,
+    };
+
+    /* Requested recurrence mode for GNSS operation. */
+    @export(name="", value_prefix="GPS_POSITION_")
+    enum GnssPositionRecurrence : uint32_t {
+        /** Receive GNSS fixes on a recurring basis at a specified period. */
+        RECURRENCE_PERIODIC  = 0,
+        /** Request a single shot GNSS fix. */
+        RECURRENCE_SINGLE    = 1
+    };
+
+    /*
+     * Flags used to specify which aiding data to delete when calling
+     * deleteAidingData().
+     */
+    @export(name="", value_prefix="GPS_")
+    enum GnssAidingData : uint16_t {
+        DELETE_EPHEMERIS    = 0x0001,
+        DELETE_ALMANAC      = 0x0002,
+        DELETE_POSITION     = 0x0004,
+        DELETE_TIME         = 0x0008,
+        DELETE_IONO         = 0x0010,
+        DELETE_UTC          = 0x0020,
+        DELETE_HEALTH       = 0x0040,
+        DELETE_SVDIR        = 0x0080,
+        DELETE_SVSTEER      = 0x0100,
+        DELETE_SADATA       = 0x0200,
+        DELETE_RTI          = 0x0400,
+        DELETE_CELLDB_INFO  = 0x8000,
+        DELETE_ALL          = 0xFFFF
+    };
+
+    /*
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     *
+     * @param callback Callback interface for IGnss.
+     *
+     * @return success Returns true on success.
+     */
+    setCallback(IGnssCallback callback) generates (bool success);
+
+    /*
+     * Starts a location output stream using the IGnssCallback
+     * gnssLocationCb(), following the settings from the most recent call to
+     * setPositionMode().
+     *
+     * This output must operate independently of any GNSS location batching
+     * operations, see the IGnssBatching.hal for details.
+     *
+     * @return success Returns true on success.
+     */
+    start() generates (bool success);
+
+    /*
+     * Stops the location output stream.
+     *
+     * @return success Returns true on success.
+     */
+    stop() generates (bool success);
+
+    /*
+     * Closes the interface.
+     */
+    cleanup();
+
+    /*
+     * Injects the current time.
+     *
+     * @param timeMs This is the UTC time received from the NTP server, its value
+     * is given in milliseconds since January 1, 1970.
+     * @param timeReferenceMs The corresponding value of
+     * SystemClock.elapsedRealtime() from the device when the NTP response was
+     * received in milliseconds.
+     * @param uncertaintyMs Uncertainty associated with the value represented by
+     * time. Represented in milliseconds.
+     *
+     * @return success Returns true if the operation is successful.
+     */
+    injectTime(GnssUtcTime timeMs, int64_t timeReferenceMs, int32_t uncertaintyMs)
+        generates (bool success);
+
+    /*
+     * Injects current location from another location provider (typically cell
+     * ID).
+     *
+     * @param latitudeDegrees Measured in Degrees.
+     * @param longitudeDegrees Measured in Degrees.
+     * @param accuracyMeters Measured in meters.
+     *
+     * @return success Returns true if successful.
+     */
+    injectLocation(double latitudeDegrees, double longitudeDegrees, float accuracyMeters)
+        generates (bool success);
+
+    /*
+     * Specifies that the next call to start will not use the
+     * information defined in the flags. GnssAidingData value of DELETE_ALL is
+     * passed for a cold start.
+     *
+     * @param aidingDataFlags Flags specifying the aiding data to be deleted.
+     */
+    deleteAidingData(GnssAidingData aidingDataFlags);
+
+    /*
+     * Sets the GnssPositionMode parameter,its associated recurrence value,
+     * the time between fixes,requested fix accuracy and time to first fix.
+     *
+     * @param mode  Parameter must be one of MS_BASED or STANDALONE.
+     * It is allowed by the platform (and it is recommended) to fallback to
+     * MS_BASED if MS_ASSISTED is passed in, and MS_BASED is supported.
+     * @recurrence GNSS postion recurrence value, either periodic or single.
+     * @param minIntervalMs Represents the time between fixes in milliseconds.
+     * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
+     * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
+
+     * @return success Returns true if successful.
+     */
+    setPositionMode(GnssPositionMode mode, GnssPositionRecurrence recurrence,
+                    uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+                    uint32_t preferredTimeMs)
+        generates (bool success);
+
+    /*
+     * This method returns the IAGnssRil Interface.
+     *
+     * @return aGnssRilIface Handle to the IAGnssRil interface.
+     */
+    getExtensionAGnssRil() generates (IAGnssRil aGnssRilIface);
+
+    /*
+     * This method returns the IGnssGeofencing Interface.
+     *
+     * @return gnssGeofencingIface Handle to the IGnssGeofencing interface.
+     */
+    getExtensionGnssGeofencing() generates(IGnssGeofencing gnssGeofencingIface);
+
+    /*
+     * This method returns the IAGnss Interface.
+     *
+     * @return aGnssIface Handle to the IAGnss interface.
+     */
+    getExtensionAGnss() generates (IAGnss aGnssIface);
+
+    /*
+     * This method returns the IGnssNi interface.
+     *
+     * @return gnssNiIface Handle to the IGnssNi interface.
+     */
+    getExtensionGnssNi() generates (IGnssNi gnssNiIface);
+
+    /*
+     * This method returns the IGnssMeasurement interface.
+     *
+     * @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
+     */
+    getExtensionGnssMeasurement() generates (IGnssMeasurement gnssMeasurementIface);
+
+    /*
+     * This method returns the IGnssNavigationMessage interface.
+     *
+     * @return gnssNavigationIface gnssNavigationIface to the IGnssNavigationMessage interface.
+     */
+    getExtensionGnssNavigationMessage() generates (IGnssNavigationMessage gnssNavigationIface);
+
+    /*
+     * This method returns the IGnssXtra interface.
+     *
+     * @return xtraIface Handle to the IGnssXtra interface.
+     */
+    getExtensionXtra() generates (IGnssXtra xtraIface);
+
+    /*
+     * This method returns the IGnssConfiguration interface.
+     *
+     * @return gnssConfigIface Handle to the IGnssConfiguration interface.
+     */
+    getExtensionGnssConfiguration() generates (IGnssConfiguration gnssConfigIface);
+
+    /*
+     * This method returns the IGnssDebug interface.
+     *
+     * @return debugIface Handle to the IGnssDebug interface.
+     */
+    getExtensionGnssDebug() generates (IGnssDebug debugIface);
+
+    /*
+     * This method returns the IGnssBatching interface.
+     *
+     * @return batchingIface Handle to the IGnssBatching interface.
+     */
+    getExtensionGnssBatching() generates (IGnssBatching batchingIface);
+};
diff --git a/gnss/1.0/IGnssBatching.hal b/gnss/1.0/IGnssBatching.hal
new file mode 100644
index 0000000..4d5affa
--- /dev/null
+++ b/gnss/1.0/IGnssBatching.hal
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IGnssBatchingCallback;
+
+/*
+ * Extended interface for GNSS Batching support.
+ *
+ * If this interface is supported, this batching request must be able to run in
+ * parallel with, or without, non-batched location requested by the
+ * IGnss start() & stop() - i.e. both requests must be handled independently,
+ * and not interfere with each other.
+ *
+ * For example, if a 1Hz continuous output is underway on the IGnssCallback,
+ * due to an IGnss start() operation,
+ * and then a IGnssBatching start() is called for a location every 10
+ * seconds, the newly added batching request must not disrupt the 1Hz
+ * continuous location output on the IGnssCallback.
+ *
+ * As with GNSS Location outputs, source of location must be GNSS satellite
+ * measurements, optionally using interial and baro sensors to improve
+ * relative motion filtering. No additional absolute positioning information,
+ * such as WiFi derived location, may be mixed with the GNSS information.
+ */
+
+interface IGnssBatching {
+    /*
+     * Enum which holds the bit masks for batching control.
+     */
+    @export(name="", value_prefix="FLP_BATCH_")
+    enum Flag : uint8_t {
+        /*
+         * If this flag is set, the hardware implementation
+         * must wake up the application processor when the FIFO is full, and
+         * call IGnssBatchingCallback to return the locations.
+         *
+         * If the flag is not set, the hardware implementation must drop
+         * the oldest data when the FIFO is full.
+         */
+        WAKEUP_ON_FIFO_FULL = 0x01
+    };
+
+    struct Options {
+        /*
+         * Time interval between samples in the location batch, in nano
+         * seconds.
+         */
+        int64_t periodNanos;
+
+        /*
+         * Flags controlling how batching should behave.
+         */
+        bitfield<Flag> flags;
+    };
+
+    /*
+     * Opens the interface and provides the callback routines
+     * to the implementation of this interface.
+     *
+     * @param callback Callback interface for IGnssBatching.
+     *
+     * @return success Returns true on success.
+     */
+    init(IGnssBatchingCallback callback) generates (bool success);
+
+    /*
+     * Return the batch size (in number of GnssLocation objects)
+     * available in this hardware implementation.
+     *
+     * If the available size is variable, for example, based on other operations
+     * consuming memory, this is the minimum size guaranteed to be available
+     * for batching operations.
+     *
+     * This may, for example, be used by the upper layer, to decide on the
+     * batching interval and whether the AP should be woken up or not.
+     *
+     * @return batchSize number of location objects supported per batch
+     */
+    getBatchSize() generates (uint16_t batchSize);
+
+    /*
+     * Start batching locations. This API is primarily used when the AP is
+     * asleep and the device can batch locations in the hardware.
+     *
+     * IGnssBatchingCallback is used to return the locations.
+     *
+     * When the buffer is full and WAKEUP_ON_FIFO_FULL is used,
+     * IGnssBatchingCallback must be called to return the locations.
+     *
+     * When the buffer is full and WAKEUP_ON_FIFO_FULL is not set,
+     * the oldest location object is dropped. In this case the AP must not be
+     * woken up. The AP would then generally be responsible for using
+     * flushBatchedLocation to explicitly ask for the location as needed,
+     * to avoid it being dropped.
+     *
+     * @param options See struct Options definition.
+     *
+     * @return success Returns true on success.
+     */
+    start(Options options) generates (bool success);
+
+    /**
+     * Retrieve all batched locations currently stored.
+     *
+     * IGnssBatchingCallback is used to return the location.
+     *
+     * IGnssBatchingCallback must be called in response, even if there are
+     * no locations to flush (in which case the Location vector must be empty).
+     *
+     * Subsequent calls to flushBatchedLocation
+     * must not return any of the locations returned in this call.
+     */
+    flush();
+
+    /**
+     * Stop batching.
+     *
+     * @return success Returns true on success.
+     */
+    stop() generates (bool success);
+
+    /**
+     * Closes the interface. If any batch operations are in progress,
+     * they should be stopped.
+     *
+     * init() may be called again, after this, if the interface is to be restored
+     */
+    cleanup();
+
+};
diff --git a/gnss/1.0/IGnssBatchingCallback.hal b/gnss/1.0/IGnssBatchingCallback.hal
new file mode 100644
index 0000000..a8f4b88
--- /dev/null
+++ b/gnss/1.0/IGnssBatchingCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/* The callback interface to report measurements from the HAL. */
+interface IGnssBatchingCallback {
+    /*
+     * Called when a batch of locations is output, by various means, including
+     * a flush request, as well as the buffer becoming full (if appropriate option
+     * is set.)
+     *
+     * All locations returned by this callback must be cleared from the hardware
+     * buffer, such the sequential calls of this callback do not return any
+     * redundant locations.  (Same lat/lon, at a new time, is acceptable.)
+     *
+     * @param locations GNSS Location information from HAL.
+     */
+    gnssLocationBatchCb(vec<GnssLocation> locations);
+};
diff --git a/gnss/1.0/IGnssCallback.hal b/gnss/1.0/IGnssCallback.hal
new file mode 100644
index 0000000..0c3b9f0
--- /dev/null
+++ b/gnss/1.0/IGnssCallback.hal
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/*
+ * The interface is required for the HAL to communicate certain information
+ * like status and location info back to the platform, the platform implements
+ * the interfaces and passes a handle to the HAL.
+ */
+interface IGnssCallback {
+    /* Flags for the gnssSetCapabilities callback. */
+    @export(name="", value_prefix="GPS_CAPABILITY_")
+    enum Capabilities : uint32_t {
+        /*
+         * GNSS HAL schedules fixes for RECURRENCE_PERIODIC mode.
+         * If this is not set, then the framework will use 1000ms for
+         * minInterval and will call start() and stop() to schedule the GNSS.
+         */
+        SCHEDULING                      = 1 << 0,
+        /** GNSS supports MS-Based AGNSS mode */
+        MSB                             = 1 << 1,
+        /** GNSS supports MS-Assisted AGNSS mode */
+        MSA                             = 1 << 2,
+        /** GNSS supports single-shot fixes */
+        SINGLE_SHOT                     = 1 << 3,
+        /** GNSS supports on demand time injection */
+        ON_DEMAND_TIME                  = 1 << 4,
+        /** GNSS supports Geofencing  */
+        GEOFENCING                      = 1 << 5,
+        /** GNSS supports Measurements for at least GPS. */
+        MEASUREMENTS                    = 1 << 6,
+        /** GNSS supports Navigation Messages */
+        NAV_MESSAGES                    = 1 << 7
+    };
+
+    /* GNSS status event values. */
+    @export(name="", value_prefix="GPS_STATUS_")
+    enum GnssStatusValue : uint8_t {
+        /** GNSS status unknown. */
+        NONE           = 0,
+        /** GNSS has begun navigating. */
+        SESSION_BEGIN  = 1,
+        /** GNSS has stopped navigating. */
+        SESSION_END    = 2,
+        /** GNSS has powered on but is not navigating. */
+        ENGINE_ON      = 3,
+        /** GNSS is powered off. */
+        ENGINE_OFF     = 4
+    };
+
+    /*
+     * Flags that indicate information about the satellite
+     */
+    @export(name="", value_prefix="GNSS_SV_FLAGS_")
+    enum GnssSvFlags : uint8_t {
+        NONE                  = 0,
+        HAS_EPHEMERIS_DATA    = 1 << 0,
+        HAS_ALMANAC_DATA      = 1 << 1,
+        USED_IN_FIX           = 1 << 2,
+        HAS_CARRIER_FREQUENCY = 1 << 3
+    };
+
+    struct GnssSvInfo {
+        /*
+         * Pseudo-random number for the SV, or FCN/OSN number for Glonass. The
+         * distinction is made by looking at constellation field. Values must be
+         * in the range of:
+         *
+         * - GNSS:    1-32
+         * - SBAS:    120-151, 183-192
+         * - GLONASS: 1-24, the orbital slot number (OSN), if known.  Or, if not:
+         *            93-106, the frequency channel number (FCN) (-7 to +6) offset by
+         *            + 100
+         *            i.e. report an FCN of -7 as 93, FCN of 0 as 100, and FCN of +6
+         *            as 106.
+         * - QZSS:    193-200
+         * - Galileo: 1-36
+         * - Beidou:  1-37
+         */
+        int16_t svid;
+
+        /*
+         * Defines the constellation of the given SV.
+         */
+        GnssConstellationType constellation;
+
+        /*
+         * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+         * It contains the measured C/N0 value for the signal at the antenna port.
+         *
+         * This is a mandatory value.
+         */
+        float cN0Dbhz;
+
+        /** Elevation of SV in degrees. */
+        float elevationDegrees;
+
+        /** Azimuth of SV in degrees. */
+        float azimuthDegrees;
+
+        /*
+         * Carrier frequency of the signal tracked, for example it can be the
+         * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
+         * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it
+         * is the primary common use central frequency, e.g. L1 = 1575.45 MHz
+         * for GPS.
+         *
+         * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
+         * time, two GnssSvInfo structs must be reported for this same
+         * satellite, in one of the structs, all the values related
+         * to L1 must be filled, and in the other all of the values related to
+         * L5 must be filled.
+         *
+         * If the data is available, gnssClockFlags must contain
+         * HAS_CARRIER_FREQUENCY.
+         */
+        float carrierFrequencyHz;
+
+        /*
+         * Contains additional data about the given SV.
+         */
+        bitfield<GnssSvFlags> svFlag;
+    };
+
+    /*
+     * Represents SV status.
+     */
+    struct GnssSvStatus {
+        /*
+         * Number of GNSS SVs currently visible, refers to the SVs stored in sv_list
+         */
+        uint32_t numSvs;
+
+        /*
+         * Pointer to an array of SVs information for all GNSS constellations,
+         * except GNSS, which is reported using svList
+         */
+        GnssSvInfo[GnssMax:SVS_COUNT] gnssSvList;
+
+    };
+
+    /*
+     * Called when a GNSS location is available.
+     *
+     * @param location Location information from HAL.
+     */
+    gnssLocationCb(GnssLocation location);
+
+    /*
+     * Called to communicate the status of the GNSS engine.
+     *
+     * @param status Status information from HAL.
+     */
+    gnssStatusCb(GnssStatusValue status);
+
+    /*
+     * @param svInfo SV status information from HAL.
+     */
+    gnssSvStatusCb(GnssSvStatus svInfo);
+
+    /*
+     * Called when NMEA data is available.
+     * Callback for reporting NMEA sentences.
+     *
+     * @param timestamp Marks the instance of reporting.
+     * @param nmea Follows standard NMEA 0183. Each sentence begins with a '$'
+     * and ends with a carriage return/line feed sequence and can be no longer
+     * than 80 characters of visible text (plus the line terminators). The data
+     * is contained within this single line with data items separated by commas.
+     * The data itself is just ascii text and may extend over multiple sentences
+     * in certain specialized instances but is normally fully contained in one
+     * variable length sentence. The data may vary in the amount of precision
+     * contained in the message. For example time might be indicated to decimal
+     * parts of a second or location may be shown with 3 or even 4 digits after
+     * the decimal point. Programs that read the data must only use the commas
+     * to determine the field boundaries and not depend on column positions.
+     * There is a provision for a checksum at the end of each sentence which may
+     * or may not be checked by the unit that reads the data. The checksum field
+     * consists of a '*' and two hex digits representing an 8 bit exclusive OR
+     * of all characters between, but not including, the '$' and '*'.
+     */
+    gnssNmeaCb(GnssUtcTime timestamp, string nmea);
+
+    /*
+     * Callback to inform framework of the GNSS engine's capabilities.
+     *
+     * @param capabilities Capability parameter is a bit field of
+     * the Capabilities enum.
+     */
+    gnssSetCapabilitesCb(bitfield<Capabilities> capabilities);
+
+    /*
+     * Callback utility for acquiring the GNSS wakelock. This can be used to prevent
+     * the CPU from suspending while handling GNSS events.
+     */
+    gnssAcquireWakelockCb();
+
+    /** Callback utility for releasing the GNSS wakelock. */
+    gnssReleaseWakelockCb();
+
+    /** Callback for requesting NTP time */
+    gnssRequestTimeCb();
+
+    /*
+     * Provides information about how new the underlying GPS/GNSS hardware and
+     * software is.
+     *
+     * This information will be available for Android Test Applications. If a GNSS
+     * HAL does not provide this information, it will be considered "2015 or
+     * earlier".
+     *
+     * If a GNSS HAL does provide this information, then newer years will need to
+     * meet newer CTS standards. E.g. if the date are 2016 or above, then N+ level
+     * GnssMeasurement support will be verified.
+     */
+    struct GnssSystemInfo{
+        /*
+         * year in which the last update was made to the underlying hardware/firmware
+         * used to capture GNSS signals, e.g. 2016
+         */
+        uint16_t yearOfHw;
+    };
+
+    /*
+     * Callback to inform framework of the engine's hardware version information.
+     *
+     * @param info GnssSystemInfo about the GPS/GNSS hardware.
+     */
+    gnssSetSystemInfoCb(GnssSystemInfo info);
+};
diff --git a/gnss/1.0/IGnssConfiguration.hal b/gnss/1.0/IGnssConfiguration.hal
new file mode 100644
index 0000000..2fb6e4e
--- /dev/null
+++ b/gnss/1.0/IGnssConfiguration.hal
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+interface IGnssConfiguration {
+    /*
+     * Enum which holds the bit masks for SUPL_MODE configuration parameter.
+     */
+    enum SuplMode : uint8_t {
+        /* Mobile Station Based */
+        MSB = 0x01,
+
+        /* Mobile Station Assisted */
+        MSA = 0x02
+    };
+
+    /*
+     * Enum which holds the bit masks for GPS_LOCK configuration parameter.
+     */
+    enum GpsLock : uint8_t {
+        /* Lock Mobile Originated GPS functionalitues. */
+        MO    =  0x01,
+
+        /* Lock Network initiated GPS functionalities. */
+        NI    =  0x02
+    };
+
+    /*
+     * Enum that hold the bit masks for various LTE Positioning Profile settings (LPP_PROFILE
+     * configuration parameter). If none of the bits in the enum are set, the default setting is
+     * Radio Resource Location Protocol(RRLP).
+     */
+    enum LppProfile : uint8_t {
+        /* Enable LTE Positioning Protocol user plane */
+        USER_PLANE          = 0x01,
+
+        /* Enable LTE Positioning Protocol Control plane */
+        CONTROL_PLANE       = 0x02
+    };
+
+    /*
+     * Enum which holds the bit masks for A_GLONASS_POS_PROTOCOL_SELECT
+     * configuration parameter.
+     */
+    enum GlonassPosProtocol : uint8_t {
+        /* Radio Resource Control(RRC) control-plane. */
+        RRC_CPLANE                  = 0x01,
+
+        /* Radio Resource Location user-plane. */
+        RRLP_CPLANE                 = 0x02,
+
+        /* LTE Positioning Protocol User plane */
+        LPP_UPLANE                  = 0x04
+    };
+
+    /*
+     * IMPORTANT: GNSS HAL must expect the below methods to be called multiple
+     * times. They can be called even when GnssLocationProvider is already
+     * constructed and enabled. GNSS HAL must maintain the existing requests
+     * for various callbacks regardless the change in configuration data.
+     */
+
+     /*
+      * This method enables or disables emergency SUPL.
+      *
+      * @param enabled True if emergency SUPL is to be enabled.
+      *
+      * @return success True if operation was successful.
+      */
+     setSuplEs(bool enabled) generates (bool success);
+
+     /*
+      * This method sets the SUPL version requested by Carrier. The GNSS HAL
+      * must use this version of the SUPL protocol if supported.
+      *
+      * @param version SUPL version requested by carrier. This is a bit mask
+      * with bits 0:7 representing a service indicator field, bits 8:15
+      * representing the minor version and bits 16:23 representing the
+      * major version.
+      *
+      * @return success True if operation was successful.
+      */
+     setSuplVersion(uint32_t version) generates (bool success);
+
+     /*
+      * This method sets the SUPL mode.
+      *
+      * @param mode Bit mask that specifies the SUPL mode which is set with the SuplMode enum.
+      *
+      * @return success True if operation was successful.
+      */
+     setSuplMode(bitfield<SuplMode> mode) generates (bool success);
+
+     /*
+      * This setting configures how GPS functionalities should be locked when
+      * user turns off GPS On setting.
+      *
+      * @param lock Bitmask that specifies the GPS functionalities to be be
+      * locked as per the GpsLock enum.
+      *
+      * @return success True if operation was successful.
+      */
+     setGpsLock(bitfield<GpsLock> lock) generates (bool success);
+
+     /*
+      * This method sets the LTE Positioning Profile configuration.
+      *
+      * @param lppProfile Bitmask that specifies the LTE Positioning Profile
+      * configuration to be set as per the LppProfile enum.
+      *
+      * @return success True if operation was successful.
+      */
+     setLppProfile(bitfield<LppProfile> lppProfile) generates (bool success);
+
+     /*
+      * This method selects positioning protocol on A-Glonass system.
+      *
+      * @param protocol Bitmask that specifies the positioning protocol to be
+      * set as per GlonassPosProtocol enum.
+      *
+      * @return success True if operation was successful.
+      */
+     setGlonassPositioningProtocol(bitfield<GlonassPosProtocol> protocol) generates (bool success);
+
+     /*
+      * This method configures which PDN to use.
+      *
+      * @param enable Use emergency PDN if true and regular PDN if false.
+      * @return success True if operation was successful.
+      */
+     setEmergencySuplPdn(bool enable) generates (bool success);
+};
diff --git a/gnss/1.0/IGnssDebug.hal b/gnss/1.0/IGnssDebug.hal
new file mode 100644
index 0000000..8784d1a
--- /dev/null
+++ b/gnss/1.0/IGnssDebug.hal
@@ -0,0 +1,139 @@
+package android.hardware.gnss@1.0;
+
+/* Extended interface for DEBUG support. */
+interface IGnssDebug {
+    enum SatelliteEphemerisType : uint8_t {
+        /* no information is known to the gnss hardware, about this satellite */
+        UNKNOWN,
+        /*  this satellite is known to exist */
+        KNOWN,
+        /*  this satellite is not known to exist */
+        NONEXISTENT,
+        /* Only Almanac (approximate) location known for this satellite */
+        ALMANAC_ONLY,
+        /* Ephemeris is known from demodulating the signal on device */
+        DEMODULATED,
+        /* Ephemeris has been provided by SUPL */
+        SUPL_PROVIDED,
+        /* Ephemeris has been provided by another server */
+        OTHER_SERVER_PROVIDED,
+        /*
+         * Predicted ephemeris has been provided by a server
+         * (e.g. Xtra, Extended Ephemeris, etc...)
+         */
+        SERVER_PREDICTED,
+        /*
+         * Predicted ephemeris in use, generated locally on the device (e.g. from prior
+         * ephemeris)
+         */
+        LOCALLY_PREDICTED
+    };
+
+    /*
+     * Provides the current best known position from any
+     * source (GNSS or injected assistance).
+     */
+    struct PositionDebug {
+        /*
+         * Validity of the data in this struct. False only if no
+         * latitude/longitude information is known.
+         */
+        bool valid;
+        /* Latitude expressed in degrees */
+        double latitudeDegrees;
+        /* Longitude expressed in degrees */
+        double longitudeDegrees;
+        /* Altitude above ellipsoid expressed in meters */
+        float altitudeMeters;
+        /* Represents speed in meters per second. */
+        float speedMetersPerSec;
+        /* Represents heading in degrees. */
+        float bearingDegrees;
+        /*
+         * estimated horizontal accuracy of position expressed in meters, radial,
+         * 68% confidence.
+         */
+        double horizontalAccuracyMeters;
+        /*
+         * estimated vertical accuracy of position expressed in meters, with
+         * 68% confidence.
+         */
+        double verticalAccuracyMeters;
+        /*
+         * estimated speed accuracy in meters per second with 68% confidence.
+         */
+        double speedAccuracyMetersPerSecond;
+        /*
+         * estimated bearing accuracy degrees with 68% confidence.
+         */
+        double bearingAccuracyDegrees;
+        /*
+         * Time duration before this report that this position information was
+         * valid.
+         */
+        float ageSeconds;
+    };
+
+    /*
+     * Provides the current best known UTC time estimate.
+     */
+    struct TimeDebug {
+        /*
+         * Validity of the data in the struct.
+         * False if current time is unknown.
+         */
+        bool valid;
+        /*
+         * UTC time estimate.
+         */
+        GnssUtcTime timeEstimate;
+        /* 68% error estimate in time. */
+        float timeUncertaintyNs;
+    };
+
+    /*
+     * Provides a single satellite info that has decoded navigation data.
+     */
+    struct SatelliteData {
+        /* Satellite vehicle ID number */
+        int16_t svid;
+        /* Defines the constellation type of the given SV. */
+        GnssConstellationType constellation;
+        /* Defines the ephemeris type of the satellite. */
+        SatelliteEphemerisType ephemerisType;
+        /*
+         * Time duration before this report, that the ephemeris source was last
+         * updated, e.g. latest demodulation, or latest server download.
+         * Set to 0 when ephemerisType is UNKNOWN.
+         */
+        float ephemerisAgeSeconds;
+    };
+
+    /*
+     * Provides a set of debug information that is filled by the GNSS chipset
+     * when the method getDebugData() is invoked.
+     */
+    struct DebugData {
+        /* Current best known position. */
+        PositionDebug position;
+        /* Current best know time estimate */
+        TimeDebug time;
+        /*
+         * Provides a list of the decoded satellite ephemeris.
+         * Must provide a complete list for all constellations device can track,
+         * including GnssConstellationType UNKNOWN.
+         */
+        vec<SatelliteData> satelliteDataArray;
+
+    };
+
+    /*
+     * This methods requests position, time and satellite ephemeris debug information
+     * from the HAL.
+     *
+     * @return ret debugData information from GNSS Hal that contains the current best
+     * known position, best known time estimate and a complete list of
+     * constellations that the device can track.
+     */
+    getDebugData() generates (DebugData debugData);
+};
diff --git a/gnss/1.0/IGnssGeofenceCallback.hal b/gnss/1.0/IGnssGeofenceCallback.hal
new file mode 100644
index 0000000..722317e
--- /dev/null
+++ b/gnss/1.0/IGnssGeofenceCallback.hal
@@ -0,0 +1,191 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/*
+ * GNSS Geofence.
+ * There are 3 states associated with a Geofence: Inside, Outside, Unknown.
+ * There are 3 transitions: ENTERED, EXITED, UNCERTAIN.
+ *
+ * An example state diagram with confidence level: 95% and Unknown time limit
+ * set as 30 secs is shown below. (confidence level and Unknown time limit are
+ * explained latter).
+ *                         ____________________________
+ *                        |       Unknown (30 secs)   |
+ *                         """"""""""""""""""""""""""""
+ *                            ^ |                  |  ^
+ *                   UNCERTAIN| |ENTERED     EXITED|  |UNCERTAIN
+ *                            | v                  v  |
+ *                        ________    EXITED     _________
+ *                       | Inside | -----------> | Outside |
+ *                       |        | <----------- |         |
+ *                        """"""""    ENTERED    """""""""
+ *
+ * Inside state: We are 95% confident that the user is inside the geofence.
+ * Outside state: We are 95% confident that the user is outside the geofence
+ * Unknown state: Rest of the time.
+ *
+ * The Unknown state is better explained with an example:
+ *
+ *                            __________
+ *                           |         c|
+ *                           |  ___     |    _______
+ *                           |  |a|     |   |   b   |
+ *                           |  """     |    """""""
+ *                           |          |
+ *                            """"""""""
+ * In the diagram above, "a" and "b" are 2 geofences and "c" is the accuracy
+ * circle reported by the GNSS subsystem. Now with regard to "b", the system is
+ * confident that the user is outside. But with regard to "a" is not confident
+ * whether it is inside or outside the geofence. If the accuracy remains the
+ * same for a sufficient period of time, the UNCERTAIN transition must be
+ * triggered with the state set to Unknown. If the accuracy improves later, an
+ * appropriate transition must be triggered.  This "sufficient period of time"
+ * is defined by the parameter in the addGeofenceArea API.
+ * In other words, Unknown state can be interpreted as a state in which the
+ * GNSS subsystem isn't confident enough that the user is either inside or
+ * outside the Geofence. It moves to Unknown state only after the expiry of the
+ * timeout.
+ *
+ * The geofence callback needs to be triggered for the ENTERED and EXITED
+ * transitions, when the GNSS system is confident that the user has entered
+ * (Inside state) or exited (Outside state) the Geofence. An implementation
+ * which uses a value of 95% as the confidence is recommended. The callback
+ * must be triggered only for the transitions requested by the
+ * addGeofenceArea method.
+ *
+ * Even though the diagram and explanation talks about states and transitions,
+ * the callee is only interested in the transitions. The states are mentioned
+ * here for illustrative purposes.
+ *
+ * Startup Scenario: When the device boots up, if an application adds geofences,
+ * and then we get an accurate GNSS location fix, it needs to trigger the
+ * appropriate (ENTERED or EXITED) transition for every Geofence it knows about.
+ * By default, all the Geofences will be in the Unknown state.
+ *
+ * When the GNSS system is unavailable, gnssGeofenceStatusCb must be
+ * called to inform the upper layers of the same. Similarly, when it becomes
+ * available the callback must be called. This is a global state while the
+ * UNKNOWN transition described above is per geofence.
+ *
+ * An important aspect to note is that users of this API (framework), will use
+ * other subsystems like wifi, sensors, cell to handle Unknown case and
+ * hopefully provide a definitive state transition to the third party
+ * application. GNSS Geofence will just be a signal indicating what the GNSS
+ * subsystem knows about the Geofence.
+ *
+ */
+
+interface IGnssGeofenceCallback {
+    @export(name="", value_prefix="GPS_GEOFENCE_")
+    enum GeofenceTransition : int32_t {
+        ENTERED   = (1 << 0L),
+        EXITED    = (1 << 1L),
+        UNCERTAIN = (1 << 2L),
+    };
+
+    @export(name="", value_prefix="GPS_GEOFENCE_")
+    enum GeofenceAvailability : int32_t {
+        UNAVAILABLE = (1 << 0L),
+        AVAILABLE   = (1 << 1L),
+    };
+
+    @export(name="", value_prefix="GPS_GEOFENCE_")
+    enum GeofenceStatus : int32_t {
+        OPERATION_SUCCESS        = 0,
+        ERROR_TOO_MANY_GEOFENCES = -100,
+        ERROR_ID_EXISTS          = -101,
+        ERROR_ID_UNKNOWN         = -102,
+        ERROR_INVALID_TRANSITION = -103,
+        ERROR_GENERIC            = -149
+    };
+
+    /*
+     * The callback associated with the geofence transition.
+     * The callback must only be called when the caller is interested in that
+     * particular transition. For instance, if the caller is interested only in
+     * ENTERED transition, then the callback must not be called with the EXITED
+     * transition.
+     *
+     * IMPORTANT: If a transition is triggered resulting in this callback, the
+     * GNSS subsystem will wake up the application processor, if its in suspend
+     * state.
+     *
+     * @param geofenceId The id associated with the addGeofenceArea.
+     * @param location The current GNSS location.
+     * @param transition Can be one of ENTERED, EXITED or UNCERTAIN.
+     * @param timestamp Timestamp when the transition was detected.
+     *
+     */
+    gnssGeofenceTransitionCb(int32_t geofenceId, GnssLocation location,
+        GeofenceTransition transition, GnssUtcTime timestamp);
+
+    /*
+     * The callback associated with the availability of the GNSS system for
+     * geofencing monitoring. If the GNSS system determines that it cannot monitor
+     * geofences because of lack of reliability or unavailability of the GNSS
+     * signals, it will call this callback with UNAVAILABLE parameter.
+     *
+     * @param status - UNAVAILABLE or AVAILABLE.
+     * @param lastLocation - Last known location.
+     */
+    gnssGeofenceStatusCb(GeofenceAvailability status, GnssLocation lastLocation);
+
+    /*
+     * The callback associated with the addGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Will be OPERATION_SUCCESS if the geofence
+     * add was successful. Will be ERROR_TOO_MANY_GEOFENCES if the
+     * geofence limit has been reached.
+     * Will be ERROR_ID_EXISTS if geofence with id already exists.
+     * Will be ERROR_INVALID_TRANSITION if the monitorTransition contains an
+     * invalid transition.
+     * Will be ERROR_GENERIC for other errors.
+     */
+    gnssGeofenceAddCb(int32_t geofenceId, GeofenceStatus status);
+
+    /*
+     * The callback associated with the removeGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Will return OPERATION_SUCCESS if successful.
+     * Will be ERROR_ID_UNKNOWN for invalid id and
+     * ERROR_GENERIC for others.
+     */
+    gnssGeofenceRemoveCb(int32_t geofenceId, GeofenceStatus status);
+
+    /*
+     * The callback associated with the pauseGeofence call.
+     *
+     * @param geofenceId Id of the geofence.
+     * @param status Will be OPERATION_SUCCESS if success.
+     * Will be ERROR_ID_UNKNOWN for invalid id. Will be
+     * ERROR_INVALID_TRANSITION when monitorTransitions is invalid.
+     * Will be ERROR_GENERIC for other err errors.
+     */
+    gnssGeofencePauseCb(int32_t geofenceId, GeofenceStatus status);
+
+    /*
+     * The callback associated with the resumeGeofence call.
+     *
+     * @param geofenceId - Id of the geofence.
+     * @param status Will be OPERATION_SUCCESS if successful.
+     * Will be ERROR_ID_UNKNOWN for invalid id and ERROR_GENERIC for others.
+     */
+    gnssGeofenceResumeCb(int32_t geofenceId, GeofenceStatus status);
+};
diff --git a/gnss/1.0/IGnssGeofencing.hal b/gnss/1.0/IGnssGeofencing.hal
new file mode 100644
index 0000000..b8348b3
--- /dev/null
+++ b/gnss/1.0/IGnssGeofencing.hal
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IGnssGeofenceCallback;
+
+/* Extended interface for GNSS Geofencing support */
+interface IGnssGeofencing {
+    /*
+     * Opens the geofence interface and provides the callback routines
+     * to the HAL.
+     *
+     * @param callback Handle to the IGnssGeofenceCallback interface.
+     */
+    setCallback(IGnssGeofenceCallback callback);
+
+    /*
+     * Add a geofence area. This api currently supports circular geofences.
+     *
+     * @param geofenceId The id for the geofence. If a geofence with this id
+     * already exists, an error value (ERROR_ID_EXISTS) must be returned.
+     * @param latitudeDegrees The latitude(in degrees) for the geofence lastTransition.
+     * @param longtitudeDegrees The longitude(in degrees) for the geofence lastTransition.
+     * @param radiusMeters The radius(in meters) for the geofence lastTransition.
+     * @param lastTransition The current state of the geofence. For example, if
+     * the system already knows that the user is inside the geofence, this will
+     * be set to ENTERED. In most cases, it will be UNCERTAIN.
+     * @param monitorTransitions - Which transitions to monitor. Bitwise OR of
+     * ENTERED, EXITED and UNCERTAIN.
+     * @param notificationResponsivenessMs - Defines the best-effort description
+     * of how soon must the callback be called when the transition associated
+     * with the Geofence is triggered. For instance, if set to 1000 millseconds
+     * with ENTERED, the callback must be called 1000 milliseconds within entering
+     * the geofence. This parameter is defined in milliseconds.
+     * NOTE: This is not to be confused with the rate that the GNSS is polled at.
+     * It is acceptable to dynamically vary the rate of sampling the GNSS for
+     * power-saving reasons; thus the rate of sampling may be faster or slower
+     * than this.
+     * @param unknownTimerMs - The time limit after which the UNCERTAIN transition
+     * must be triggered. This parameter is defined in milliseconds.
+     */
+    addGeofence(int32_t geofenceId, double latitudeDegrees, double longitudeDegrees,
+            double radiusMeters, GeofenceTransition lastTransition,
+            bitfield<IGnssGeofenceCallback.GeofenceTransition> monitorTransitions,
+            uint32_t notificationResponsivenessMs,
+            uint32_t unknownTimerMs);
+
+    /*
+     * Pause monitoring a particular geofence.
+     *
+     * @param geofenceId The id for the geofence.
+     */
+    pauseGeofence(int32_t geofenceId);
+
+    /*
+     * Resume monitoring a particular geofence.
+     *
+     * @param geofenceId - The id for the geofence.
+     * @param monitorTransitions Specifies which transitions to monitor.
+     * It can be a bitwise OR of ENTERED, EXITED and
+     * UNCERTAIN. This supersedes the value associated
+     * provided in the addGeofenceArea call.
+     */
+    resumeGeofence(int32_t geofenceId,
+            bitfield<IGnssGeofenceCallback.GeofenceTransition> monitorTransitions);
+
+    /*
+     * Remove a geofence area. After the function returns, no notifications
+     * must be sent.
+     *
+     * @param geofenceId The id of the geofence.
+     */
+    removeGeofence(int32_t geofenceId);
+};
diff --git a/gnss/1.0/IGnssMeasurement.hal b/gnss/1.0/IGnssMeasurement.hal
new file mode 100644
index 0000000..8329442
--- /dev/null
+++ b/gnss/1.0/IGnssMeasurement.hal
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IGnssMeasurementCallback;
+
+/*
+ * Extended interface for GNSS Measurements support.
+ */
+interface IGnssMeasurement {
+    @export(name="", value_prefix="GPS_MEASUREMENT_")
+    enum GnssMeasurementStatus : int32_t {
+        SUCCESS = 0,
+        ERROR_ALREADY_INIT = -100,
+        ERROR_GENERIC = -101
+    };
+
+    /*
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'setCallback' the HAL must begin to provide updates at
+     * an average output rate of 1Hz (occasional
+     * intra-measurement time offsets in the range from 0-2000msec can be
+     * tolerated.)
+     *
+     * @param callback Handle to GnssMeasurement callback interface.
+     *
+     * @return initRet Returns SUCCESS if successful.
+     * Returns ERROR_ALREADY_INIT if a callback has already been
+     * registered without a corresponding call to 'close'.
+     * Returns ERROR_GENERIC for any other error. The HAL must
+     * not generate any other updates upon returning this error code.
+     */
+    setCallback(IGnssMeasurementCallback callback) generates (GnssMeasurementStatus initRet);
+
+    /*
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to close(), the previously registered callbacks must be
+     * considered invalid by the HAL.
+     * If close() is invoked without a previous setCallback, this function must perform
+     * no work.
+     */
+    close();
+
+};
diff --git a/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal
new file mode 100644
index 0000000..5789621
--- /dev/null
+++ b/gnss/1.0/IGnssMeasurementCallback.hal
@@ -0,0 +1,609 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/* The callback interface to report measurements from the HAL. */
+interface IGnssMeasurementCallback {
+    /*
+     * Flags to indicate what fields in GnssClock are valid.
+     */
+    @export(name="", value_prefix="GNSS_CLOCK_")
+    enum GnssClockFlags : uint16_t {
+        /** A valid 'leap second' is stored in the data structure. */
+        HAS_LEAP_SECOND        = 1 << 0,
+        /** A valid 'time uncertainty' is stored in the data structure. */
+        HAS_TIME_UNCERTAINTY   = 1 << 1,
+        /** A valid 'full bias' is stored in the data structure. */
+        HAS_FULL_BIAS          = 1 << 2,
+        /** A valid 'bias' is stored in the data structure. */
+        HAS_BIAS               = 1 << 3,
+        /** A valid 'bias uncertainty' is stored in the data structure. */
+        HAS_BIAS_UNCERTAINTY   = 1 << 4,
+        /** A valid 'drift' is stored in the data structure. */
+        HAS_DRIFT              = 1 << 5,
+        /** A valid 'drift uncertainty' is stored in the data structure. */
+        HAS_DRIFT_UNCERTAINTY  = 1 << 6
+    };
+
+    /*
+     * Flags to indicate what fields in GnssMeasurement are valid.
+     */
+    @export(name="", value_prefix="GNSS_MEASUREMENT_")
+    enum GnssMeasurementFlags : uint32_t {
+        /** A valid 'snr' is stored in the data structure. */
+        HAS_SNR                        = 1 << 0,
+        /** A valid 'carrier frequency' is stored in the data structure. */
+        HAS_CARRIER_FREQUENCY          = 1 << 9,
+        /** A valid 'carrier cycles' is stored in the data structure. */
+        HAS_CARRIER_CYCLES             = 1 << 10,
+        /** A valid 'carrier phase' is stored in the data structure. */
+        HAS_CARRIER_PHASE              = 1 << 11,
+        /** A valid 'carrier phase uncertainty' is stored in the data structure. */
+        HAS_CARRIER_PHASE_UNCERTAINTY  = 1 << 12,
+        /** A valid automatic gain control is stored in the data structure. */
+        HAS_AUTOMATIC_GAIN_CONTROL     = 1 << 13
+    };
+
+    /*
+     * Enumeration of available values for the GNSS Measurement's multipath
+     * indicator.
+     */
+    @export(name="", value_prefix="GNSS_MULTIPATH_")
+    enum GnssMultipathIndicator : uint8_t {
+        /** The indicator is not available or unknown. */
+        INDICATOR_UNKNOWN      = 0,
+        /** The measurement is indicated to be affected by multipath. */
+        INDICATOR_PRESENT      = 1,
+        /** The measurement is indicated to be not affected by multipath. */
+        INDICATIOR_NOT_PRESENT = 2
+    };
+
+    /*
+     * Flags indicating the GNSS measurement state.
+     *
+     * The expected behavior here is for GNSS HAL to set all the flags that applies.
+     * For example, if the state for a satellite is only C/A code locked and bit
+     * synchronized, and there is still millisecond ambiguity, the state must be
+     * set as:
+     *
+     * STATE_CODE_LOCK | STATE_BIT_SYNC |  STATE_MSEC_AMBIGUOUS
+     *
+     * If GNSS is still searching for a satellite, the corresponding state must be
+     * set to STATE_UNKNOWN(0).
+     */
+    @export(name="", value_prefix="GNSS_MEASUREMENT_")
+    enum GnssMeasurementState : uint32_t {
+        STATE_UNKNOWN                = 0,
+        STATE_CODE_LOCK              = 1 << 0,
+        STATE_BIT_SYNC               = 1 << 1,
+        STATE_SUBFRAME_SYNC          = 1 << 2,
+        STATE_TOW_DECODED            = 1 << 3,
+        STATE_MSEC_AMBIGUOUS         = 1 << 4,
+        STATE_SYMBOL_SYNC            = 1 << 5,
+        STATE_GLO_STRING_SYNC        = 1 << 6,
+        STATE_GLO_TOD_DECODED        = 1 << 7,
+        STATE_BDS_D2_BIT_SYNC        = 1 << 8,
+        STATE_BDS_D2_SUBFRAME_SYNC   = 1 << 9,
+        STATE_GAL_E1BC_CODE_LOCK     = 1 << 10,
+        STATE_GAL_E1C_2ND_CODE_LOCK  = 1 << 11,
+        STATE_GAL_E1B_PAGE_SYNC      = 1 << 12,
+        STATE_SBAS_SYNC              = 1 << 13,
+        STATE_TOW_KNOWN              = 1 << 14,
+        STATE_GLO_TOD_KNOWN          = 1 << 15,
+    };
+
+    /*
+     * Flags indicating the Accumulated Delta Range's states.
+     */
+    @export(name="", value_prefix="GNSS_")
+    enum GnssAccumulatedDeltaRangeState : uint16_t {
+        ADR_STATE_UNKNOWN    = 0,
+        ADR_STATE_VALID      = 1 << 0,
+        ADR_STATE_RESET      = 1 << 1,
+        ADR_STATE_CYCLE_SLIP = 1 << 2,
+    };
+
+    /*
+     * Represents an estimate of the GNSS clock time.
+     */
+    struct GnssClock {
+        /*
+         * A set of flags indicating the validity of the fields in this data
+         * structure.
+         */
+        bitfield<GnssClockFlags> gnssClockFlags;
+
+        /*
+         * Leap second data.
+         * The sign of the value is defined by the following equation:
+         *      utcTimeNs = timeNs - (fullBiasNs + biasNs) - leapSecond *
+         *      1,000,000,000
+         *
+         * If this data is available, gnssClockFlags must contain
+         * HAS_LEAP_SECOND.
+         */
+        int16_t leapSecond;
+
+        /*
+         * The GNSS receiver internal clock value. This is the local hardware clock
+         * value.
+         *
+         * For local hardware clock, this value is expected to be monotonically
+         * increasing while the hardware clock remains powered on. (For the case of a
+         * HW clock that is not continuously on, see the
+         * hwClockDiscontinuityCount field). The receiver's estimate of GNSS time
+         * can be derived by subtracting the sum of fullBiasNs and biasNs (when
+         * available) from this value.
+         *
+         * This GNSS time must be the best estimate of current GNSS time
+         * that GNSS receiver can achieve.
+         *
+         * Sub-nanosecond accuracy can be provided by means of the 'biasNs' field.
+         * The value contains the timeUncertaintyNs in it.
+         *
+         * This field is mandatory.
+         */
+        int64_t timeNs;
+
+        /*
+         * 1-Sigma uncertainty associated with the clock's time in nanoseconds.
+         * The uncertainty is represented as an absolute (single sided) value.
+         *
+         * If the data is available, gnssClockFlags must contain
+         * HAS_TIME_UNCERTAINTY. Ths value is ideally zero, as the time
+         * 'latched' by timeNs is defined as the reference clock vs. which all
+         * other times (and corresponding uncertainties) are measured.
+         */
+        double timeUncertaintyNs;
+
+        /*
+         * The difference between hardware clock ('time' field) inside GNSS receiver
+         * and the true GNSS time since 0000Z, January 6, 1980, in nanoseconds.
+         *
+         * The sign of the value is defined by the following equation:
+         *      local estimate of GNSS time = timeNs - (fullBiasNs + biasNs)
+         *
+         * This value is mandatory if the receiver has estimated GNSS time. If the
+         * computed time is for a non-GNSS constellation, the time offset of that
+         * constellation to GNSS has to be applied to fill this value. The error
+         * estimate for the sum of this and the biasNs is the biasUncertaintyNs,
+         * and the caller is responsible for using this uncertainty (it can be very
+         * large before the GNSS time has been solved for.) If the data is available
+         * gnssClockFlags must contain HAS_FULL_BIAS.
+         */
+        int64_t fullBiasNs;
+
+        /*
+         * Sub-nanosecond bias.
+         * The error estimate for the sum of this and the fullBiasNs is the
+         * biasUncertaintyNs.
+         *
+         * If the data is available gnssClockFlags must contain HAS_BIAS. If GNSS
+         * has computed a position fix. This value is mandatory if the receiver has
+         * estimated GNSS time.
+         */
+        double biasNs;
+
+        /*
+         * 1-Sigma uncertainty associated with the local estimate of GNSS time (clock
+         * bias) in nanoseconds. The uncertainty is represented as an absolute
+         * (single sided) value.
+         *
+         * If the data is available gnssClockFlags must contain
+         * HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
+         * has estimated GNSS time.
+         */
+        double biasUncertaintyNs;
+
+        /*
+         * The clock's drift in nanoseconds (per second).
+         *
+         * A positive value means that the frequency is higher than the nominal
+         * frequency, and that the (fullBiasNs + biasNs) is growing more positive
+         * over time.
+         *
+         * The value contains the 'drift uncertainty' in it.
+         * If the data is available gnssClockFlags must contain HAS_DRIFT.
+         *
+         * This value is mandatory if the receiver has estimated GNSS time.
+         */
+        double driftNsps;
+
+        /*
+         * 1-Sigma uncertainty associated with the clock's drift in nanoseconds (per
+         * second).
+         * The uncertainty is represented as an absolute (single sided) value.
+         *
+         * If the data is available gnssClockFlags must contain
+         * HAS_DRIFT_UNCERTAINTY. If GNSS has computed a position fix this
+         * field is mandatory and must be populated.
+         */
+        double driftUncertaintyNsps;
+
+        /*
+         * When there are any discontinuities in the HW clock, this field is
+         * mandatory.
+         *
+         * A "discontinuity" is meant to cover the case of a switch from one source
+         * of clock to another.  A single free-running crystal oscillator (XO)
+         * will generally not have any discontinuities, and this can be set and
+         * left at 0.
+         *
+         * If, however, the timeNs value (HW clock) is derived from a composite of
+         * sources, that is not as smooth as a typical XO, or is otherwise stopped &
+         * restarted, then this value shall be incremented each time a discontinuity
+         * occurs.  (E.g. this value can start at zero at device boot-up and
+         * increment each time there is a change in clock continuity. In the
+         * unlikely event that this value reaches full scale, rollover (not
+         * clamping) is required, such that this value continues to change, during
+         * subsequent discontinuity events.)
+         *
+         * While this number stays the same, between GnssClock reports, it can be
+         * safely assumed that the timeNs value has been running continuously, e.g.
+         * derived from a single, high quality clock (XO like, or better, that is
+         * typically used during continuous GNSS signal sampling.)
+         *
+         * It is expected, esp. during periods where there are few GNSS signals
+         * available, that the HW clock be discontinuity-free as long as possible,
+         * as this avoids the need to use (waste) a GNSS measurement to fully
+         * re-solve for the GNSS clock bias and drift, when using the accompanying
+         * measurements, from consecutive GnssData reports.
+         */
+        uint32_t hwClockDiscontinuityCount;
+
+    };
+
+    /*
+     * Represents a GNSS Measurement, it contains raw and computed information.
+     *
+     * All signal measurement information (e.g. svTime,
+     * pseudorangeRate, multipathIndicator) reported in this struct must be
+     * based on GNSS signal measurements only. You must not synthesize measurements
+     * by calculating or reporting expected measurements based on known or estimated
+     * position, velocity, or time.
+     */
+    struct GnssMeasurement{
+        /*
+         * A set of flags indicating the validity of the fields in this data
+         * structure.
+         */
+        bitfield<GnssMeasurementFlags> flags;
+
+        /*
+         * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+         * This is a mandatory value.
+         */
+        int16_t svid;
+
+        /*
+         * Defines the constellation of the given SV.
+         */
+        GnssConstellationType constellation;
+
+        /*
+         * Time offset at which the measurement was taken in nanoseconds.
+         * The reference receiver's time is specified by GnssData::clock::timeNs.
+         *
+         * The sign of timeOffsetNs is given by the following equation:
+         *      measurement time = GnssClock::timeNs + timeOffsetNs
+         *
+         * It provides an individual time-stamp for the measurement, and allows
+         * sub-nanosecond accuracy.
+         * This is a mandatory value.
+         */
+        double timeOffsetNs;
+
+        /*
+         * Per satellite sync state. It represents the current sync state for the
+         * associated satellite.
+         * Based on the sync state, the 'received GNSS tow' field must be interpreted
+         * accordingly.
+         *
+         * This is a mandatory value.
+         */
+        bitfield<GnssMeasurementState> state;
+
+        /*
+         * The received GNSS Time-of-Week at the measurement time, in nanoseconds.
+         * For GNSS & QZSS, this is the received GNSS Time-of-Week at the
+         * measurement time, in nanoseconds. The value is relative to the
+         * beginning of the current GNSS week.
+         *
+         * Given the highest sync state that can be achieved, per each satellite,
+         * valid range for this field can be:
+         * Searching       : [ 0       ] : STATE_UNKNOWN
+         * C/A code lock   : [ 0 1ms   ] : STATE_CODE_LOCK set
+         * Bit sync        : [ 0 20ms  ] : STATE_BIT_SYNC set
+         * Subframe sync   : [ 0  6s   ] : STATE_SUBFRAME_SYNC set
+         * TOW decoded     : [ 0 1week ] : STATE_TOW_DECODED set
+         * TOW Known       : [ 0 1week ] : STATE_TOW_KNOWN set
+         *
+         * Note: TOW Known refers to the case where TOW is possibly not decoded
+         * over the air but has been determined from other sources. If TOW
+         * decoded is set then TOW Known must also be set.
+         *
+         * Note: If there is any ambiguity in integer millisecond,
+         * GNSS_MEASUREMENT_STATE_MSEC_AMBIGUOUS must be set accordingly, in the
+         * 'state' field.
+         *
+         * This value must be populated if 'state' != STATE_UNKNOWN.
+         *
+         * For Glonass, this is the received Glonass time of day, at the
+         * measurement time in nanoseconds.
+         *
+         * Given the highest sync state that can be achieved, per each satellite,
+         * valid range for this field can be:
+         * Searching           : [ 0       ] : STATE_UNKNOWN set
+         * C/A code lock       : [ 0   1ms ] : STATE_CODE_LOCK set
+         * Symbol sync         : [ 0  10ms ] : STATE_SYMBOL_SYNC set
+         * Bit sync            : [ 0  20ms ] : STATE_BIT_SYNC set
+         * String sync         : [ 0    2s ] : STATE_GLO_STRING_SYNC set
+         * Time of day decoded : [ 0  1day ] : STATE_GLO_TOD_DECODED set
+         * Time of day known   : [ 0  1day ] : STATE_GLO_TOD_KNOWN set
+         *
+         * Note: Time of day known refers to the case where it is possibly not
+         * decoded over the air but has been determined from other sources. If
+         * Time of day decoded is set then Time of day known must also be set.
+         *
+         * For Beidou, this is the received Beidou time of week,
+         * at the measurement time in nanoseconds.
+         *
+         * Given the highest sync state that can be achieved, per each satellite,
+         * valid range for this field can be:
+         * Searching            : [ 0       ] : STATE_UNKNOWN set.
+         * C/A code lock        : [ 0   1ms ] : STATE_CODE_LOCK set.
+         * Bit sync (D2)        : [ 0   2ms ] : STATE_BDS_D2_BIT_SYNC set.
+         * Bit sync (D1)        : [ 0  20ms ] : STATE_BIT_SYNC set.
+         * Subframe (D2)        : [ 0  0.6s ] : STATE_BDS_D2_SUBFRAME_SYNC set.
+         * Subframe (D1)        : [ 0    6s ] : STATE_SUBFRAME_SYNC set.
+         * Time of week decoded : [ 0 1week ] : STATE_TOW_DECODED set.
+         * Time of week known   : [ 0 1week ] : STATE_TOW_KNOWN set
+         *
+         * Note: TOW Known refers to the case where TOW is possibly not decoded
+         * over the air but has been determined from other sources. If TOW
+         * decoded is set then TOW Known must also be set.
+         *
+         * For Galileo, this is the received Galileo time of week,
+         * at the measurement time in nanoseconds.
+         *
+         * E1BC code lock       : [ 0  4ms ] : STATE_GAL_E1BC_CODE_LOCK set.
+         * E1C 2nd code lock    : [ 0 100ms] : STATE_GAL_E1C_2ND_CODE_LOCK set.
+         * E1B page             : [ 0   2s ] : STATE_GAL_E1B_PAGE_SYNC set.
+         * Time of week decoded : [ 0 1week] : STATE_TOW_DECODED is set.
+         * Time of week known   : [ 0 1week] : STATE_TOW_KNOWN set
+         *
+         * Note: TOW Known refers to the case where TOW is possibly not decoded
+         * over the air but has been determined from other sources. If TOW
+         * decoded is set then TOW Known must also be set.
+         *
+         * For SBAS, this is received SBAS time, at the measurement time in
+         * nanoseconds.
+         *
+         * Given the highest sync state that can be achieved, per each satellite,
+         * valid range for this field can be:
+         * Searching    : [ 0     ] : STATE_UNKNOWN
+         * C/A code lock: [ 0 1ms ] : STATE_CODE_LOCK is set
+         * Symbol sync  : [ 0 2ms ] : STATE_SYMBOL_SYNC is set
+         * Message      : [ 0  1s ] : STATE_SBAS_SYNC is set
+         */
+        int64_t receivedSvTimeInNs;
+
+        /*
+         * 1-Sigma uncertainty of the Received GNSS Time-of-Week in nanoseconds.
+         *
+         * This value must be populated if 'state' != STATE_UNKNOWN.
+         */
+        int64_t receivedSvTimeUncertaintyInNs;
+
+        /*
+         * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
+         * It contains the measured C/N0 value for the signal at the antenna port.
+         *
+         * This is a mandatory value.
+         */
+        double cN0DbHz;
+
+        /*
+         * Pseudorange rate at the timestamp in m/s. The correction of a given
+         * Pseudorange Rate value includes corrections for receiver and satellite
+         * clock frequency errors. Ensure that this field is independent (see
+         * comment at top of GnssMeasurement struct.)
+         *
+         * It is mandatory to provide the 'uncorrected' 'pseudorange rate', and
+         * provide GnssClock's 'drift' field as well. When providing the
+         * uncorrected pseudorange rate, do not apply the corrections described above.)
+         *
+         * The value includes the 'pseudorange rate uncertainty' in it.
+         * A positive 'uncorrected' value indicates that the SV is moving away from
+         * the receiver.
+         *
+         * The sign of the 'uncorrected' 'pseudorange rate' and its relation to the
+         * sign of 'doppler shift' is given by the equation:
+         *      pseudorange rate = -k * doppler shift   (where k is a constant)
+         *
+         * This must be the most accurate pseudorange rate available, based on
+         * fresh signal measurements from this channel.
+         *
+         * It is mandatory that this value be provided at typical carrier phase PRR
+         * quality (few cm/sec per second of uncertainty, or better) - when signals
+         * are sufficiently strong & stable, e.g. signals from a GNSS simulator at >=
+         * 35 dB-Hz.
+         */
+        double pseudorangeRateMps;
+
+        /*
+         * 1-Sigma uncertainty of the pseudorangeRateMps.
+         * The uncertainty is represented as an absolute (single sided) value.
+         *
+         * This is a mandatory value.
+         */
+        double pseudorangeRateUncertaintyMps;
+
+        /*
+         * Accumulated delta range's state. It indicates whether ADR is reset or
+         * there is a cycle slip(indicating loss of lock).
+         *
+         * This is a mandatory value.
+         */
+        bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState;
+
+        /*
+         * Accumulated delta range since the last channel reset in meters.
+         * A positive value indicates that the SV is moving away from the receiver.
+         *
+         * The sign of the 'accumulated delta range' and its relation to the sign of
+         * 'carrier phase' is given by the equation:
+         * accumulated delta range = -k * carrier phase (where k is a constant)
+         *
+         * This value must be populated if 'accumulated delta range state' !=
+         * ADR_STATE_UNKNOWN.
+         * However, it is expected that the data is only accurate when:
+         *      'accumulated delta range state' == ADR_STATE_VALID.
+         */
+        double accumulatedDeltaRangeM;
+
+        /*
+         * 1-Sigma uncertainty of the accumulated delta range in meters.
+         * This value must be populated if 'accumulated delta range state' !=
+         * ADR_STATE_UNKNOWN.
+         */
+        double accumulatedDeltaRangeUncertaintyM;
+
+        /*
+         * Carrier frequency of the signal tracked, for example it can be the
+         * GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz, L5 =
+         * 1176.45 MHz, varying GLO channels, etc. If the field is not set, it
+         * is the primary common use central frequency, e.g. L1 = 1575.45 MHz
+         * for GPS.
+         *
+         * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same
+         * time, two raw measurement structs must be reported for this same
+         * satellite, in one of the measurement structs, all the values related
+         * to L1 must be filled, and in the other all of the values related to
+         * L5 must be filled.
+         *
+         * If the data is available, gnssClockFlags must contain
+         * HAS_CARRIER_FREQUENCY.
+         */
+        float carrierFrequencyHz;
+
+        /*
+         * The number of full carrier cycles between the satellite and the
+         * receiver. The reference frequency is given by the field
+         * 'carrierFrequencyHz'. Indications of possible cycle slips and
+         * resets in the accumulation of this value can be inferred from the
+         * accumulatedDeltaRangeState flags.
+         *
+         * If the data is available, gnssClockFlags must contain
+         * HAS_CARRIER_CYCLES.
+         */
+        int64_t carrierCycles;
+
+        /*
+         * The RF phase detected by the receiver, in the range [0.0, 1.0].
+         * This is usually the fractional part of the complete carrier phase
+         * measurement.
+         *
+         * The reference frequency is given by the field 'carrierFrequencyHz'.
+         * The value contains the 'carrier-phase uncertainty' in it.
+         *
+         * If the data is available, gnssClockFlags must contain
+         * HAS_CARRIER_PHASE.
+         */
+        double carrierPhase;
+
+        /*
+         * 1-Sigma uncertainty of the carrier-phase.
+         * If the data is available, gnssClockFlags must contain
+         * HAS_CARRIER_PHASE_UNCERTAINTY.
+         */
+        double carrierPhaseUncertainty;
+
+        /*
+         * An enumeration that indicates the 'multipath' state of the event.
+         *
+         * The multipath Indicator is intended to report the presence of overlapping
+         * signals that manifest as distorted correlation peaks.
+         *
+         * - if there is a distorted correlation peak shape, report that multipath
+         *   is MULTIPATH_INDICATOR_PRESENT.
+         * - if there is no distorted correlation peak shape, report
+         *   MULTIPATH_INDICATOR_NOT_PRESENT
+         * - if signals are too weak to discern this information, report
+         *   MULTIPATH_INDICATOR_UNKNOWN
+         *
+         * Example: when doing the standardized overlapping Multipath Performance
+         * test (3GPP TS 34.171) the Multipath indicator must report
+         * MULTIPATH_INDICATOR_PRESENT for those signals that are tracked, and
+         * contain multipath, and MULTIPATH_INDICATOR_NOT_PRESENT for those
+         * signals that are tracked and do not contain multipath.
+         */
+        GnssMultipathIndicator multipathIndicator;
+
+        /*
+         * Signal-to-noise ratio at correlator output in dB.
+         * If the data is available, gnssClockFlags must contain MEASUREMENT_HAS_SNR.
+         * This is the power ratio of the "correlation peak height above the
+         * observed noise floor" to "the noise RMS".
+         */
+        double snrDb;
+
+        /*
+         * Automatic gain control (AGC) level. AGC acts as a variable gain
+         * amplifier adjusting the power of the incoming signal. The AGC level
+         * may be used to indicate potential interference. When AGC is at a
+         * nominal level, this value must be set as 0. Higher gain (and/or lower
+         * input power) must be output as a positive number. Hence in cases of
+         * strong jamming, in the band of this signal, this value must go more
+         * negative.
+         *
+         * Note: Different hardware designs (e.g. antenna, pre-amplification, or
+         * other RF HW components) may also affect the typical output of of this
+         * value on any given hardware design in an open sky test - the
+         * important aspect of this output is that changes in this value are
+         * indicative of changes on input signal power in the frequency band for
+         * this measurement.
+         */
+        double agcLevelDb;
+    };
+
+    /*
+     * Represents a reading of GNSS measurements. For devices where GnssSystemInfo's
+     * yearOfHw is set to 2016+, it is mandatory that these be provided, on
+     * request, when the GNSS receiver is searching/tracking signals.
+     *
+     * - Reporting of GNSS constellation measurements is mandatory.
+     * - Reporting of all tracked constellations are encouraged.
+     */
+    struct GnssData {
+        /* Number of GnssMeasurement elements. */
+        uint32_t measurementCount;
+
+        /* The array of measurements. */
+        GnssMeasurement[GnssMax:SVS_COUNT] measurements;
+
+        /** The GNSS clock time reading. */
+        GnssClock clock;
+    };
+
+    /*
+     * Callback for the hal to pass a GnssData structure back to the client.
+     *
+     * @param data Contains a reading of GNSS measurements.
+     */
+    GnssMeasurementCb(GnssData data);
+};
diff --git a/gnss/1.0/IGnssNavigationMessage.hal b/gnss/1.0/IGnssNavigationMessage.hal
new file mode 100644
index 0000000..ddd9169
--- /dev/null
+++ b/gnss/1.0/IGnssNavigationMessage.hal
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+import IGnssNavigationMessageCallback;
+
+/*
+ * Extended interface for GNSS navigation message reporting support.
+ */
+interface IGnssNavigationMessage {
+    @export(name="", value_prefix="GPS_NAVIGATION_MESSAGE_")
+    enum GnssNavigationMessageStatus : int32_t {
+        SUCCESS = 0,
+        ERROR_ALREADY_INIT = -100,
+        ERROR_GENERIC = -101
+    };
+
+    /*
+     * Initializes the interface and registers the callback routines with the HAL.
+     * After a successful call to 'setCallback' the HAL must begin to provide updates as
+     * they become available.
+     * @param callback handle to IGnssNavigationMessageCallack interface.
+     *
+     * @return initRet Returns SUCCESS if the operation
+     * is successful.
+     * Returns ERROR_ALREADY_INIT if a callback has
+     * already been registered without a corresponding call to close().
+     * Returns ERROR_GENERIC if any other error occurred. It is
+     * expected that the HAL will not generate any updates upon returning
+     * this error code.
+     */
+     setCallback(IGnssNavigationMessageCallback callback) generates (GnssNavigationMessageStatus initRet);
+
+    /*
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to close(), the previously registered callbacks must be
+     * considered invalid by the HAL.
+     * If close() is invoked without a previous setCallback, this function must perform
+     * no work.
+     */
+    close();
+};
diff --git a/gnss/1.0/IGnssNavigationMessageCallback.hal b/gnss/1.0/IGnssNavigationMessageCallback.hal
new file mode 100644
index 0000000..2e6b853
--- /dev/null
+++ b/gnss/1.0/IGnssNavigationMessageCallback.hal
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/** Represents a GNSS navigation message (or a fragment of it). */
+interface IGnssNavigationMessageCallback {
+    /*
+     * Enumeration of available values to indicate the GNSS Navigation message
+     * types.
+     *
+     * For convenience, first byte is the GnssConstellationType on which that signal
+     * is typically transmitted.
+     */
+    @export(name="", value_prefix="GNSS_NAVIGATION_MESSAGE_TYPE_")
+    enum GnssNavigationMessageType : int16_t {
+        UNKNOWN    = 0,
+        /** GNSS L1 C/A message contained in the structure.  */
+        GNSS_L1CA       = 0x0101,
+        /** GNSS L2-CNAV message contained in the structure. */
+        GNSS_L2CNAV     = 0x0102,
+        /** GNSS L5-CNAV message contained in the structure. */
+        GNSS_L5CNAV     = 0x0103,
+        /** GNSS CNAV-2 message contained in the structure. */
+        GNSS_CNAV2      = 0x0104,
+        /** Glonass L1 CA message contained in the structure. */
+        GLO_L1CA        = 0x0301,
+        /** Beidou D1 message contained in the structure. */
+        BDS_D1          = 0x0501,
+        /** Beidou D2 message contained in the structure. */
+        BDS_D2          = 0x0502,
+        /** Galileo I/NAV message contained in the structure. */
+        GAL_I           = 0x0601,
+        /** Galileo F/NAV message contained in the structure. */
+        GAL_F           = 0x0602
+    };
+
+    /*
+     * Status of Navigation Message
+     * When a message is received properly without any parity error in its
+     * navigation words, the status must be set to PARITY_PASSED. But if a message is
+     * received with words that failed parity check, but GNSS is able to correct
+     * those words, the status must be set to PARITY_REBUILT.
+     * No need to send any navigation message that contains words with parity error
+     * and cannot be corrected.
+     */
+    @export(name="navigation_message_status", value_prefix="NAV_MESSAGE_STATUS_")
+    enum NavigationMessageStatus : uint16_t {
+        PARITY_PASSED  = (1 << 0),
+        PARITY_REBUILT = (1 << 1),
+        UNKNOWN  = 0
+    };
+
+    struct GnssNavigationMessage {
+        /*
+         * Satellite vehicle ID number, as defined in GnssSvInfo::svid
+         * This is a mandatory value.
+         */
+        int16_t svid;
+
+        /*
+         * The type of message contained in the structure.
+         * This is a mandatory value.
+         */
+        GnssNavigationMessageType type;
+
+        /*
+         * The status of the received navigation message.
+         * No need to send any navigation message that contains words with parity
+         * error and cannot be corrected.
+         */
+        bitfield<NavigationMessageStatus> status;
+
+        /*
+         * Message identifier. It provides an index so the complete Navigation
+         * Message can be assembled.
+         *
+         * - For GNSS L1 C/A subframe 4 and 5, this value corresponds to the 'frame
+         *   id' of the navigation message, in the range of 1-25 (Subframe 1, 2, 3
+         *   does not contain a 'frame id' and this value can be set to -1.)
+         *
+         * - For Glonass L1 C/A, this refers to the frame ID, in the range of 1-5.
+         *
+         * - For BeiDou D1, this refers to the frame number in the range of 1-24
+         *
+         * - For Beidou D2, this refers to the frame number, in the range of 1-120
+         *
+         * - For Galileo F/NAV nominal frame structure, this refers to the subframe
+         *   number, in the range of 1-12
+         *
+         * - For Galileo I/NAV nominal frame structure, this refers to the subframe
+         *   number in the range of 1-24
+         */
+        int16_t messageId;
+
+        /*
+         * Sub-message identifier. If required by the message 'type', this value
+         * contains a sub-index within the current message (or frame) that is being
+         * transmitted.
+         *
+         * - For GNSS L1 C/A, BeiDou D1 & BeiDou D2, the submessage id corresponds to
+         *   the subframe number of the navigation message, in the range of 1-5.
+         *
+         * - For Glonass L1 C/A, this refers to the String number, in the range from
+         *   1-15
+         *
+         * - For Galileo F/NAV, this refers to the page type in the range 1-6
+         *
+         * - For Galileo I/NAV, this refers to the word type in the range 1-10+
+         */
+        int16_t submessageId;
+
+        /*
+         * The data of the reported GNSS message. The bytes (or words) are specified
+         * using big endian format (MSB first). The data is stored and decoded
+         * in a server for research purposes.
+         *
+         * - For GNSS L1 C/A, Beidou D1 & Beidou D2, each subframe contains 10 30-bit
+         *   words. Each word (30 bits) must fit into the last 30 bits in a
+         *   4-byte word (skip B31 and B32), with MSB first, for a total of 40
+         *   bytes, covering a time period of 6, 6, and 0.6 seconds, respectively.
+         *   The standard followed is 1995 SPS Signal specification.
+         *
+         * - For Glonass L1 C/A, each string contains 85 data bits, including the
+         *   checksum.  These bits must fit into 11 bytes, with MSB first (skip
+         *   B86-B88), covering a time period of 2 seconds.
+         *   The standard followed is Glonass Interface Control Document Edition 5.1.
+         *
+         * - For Galileo F/NAV, each word consists of 238-bit (sync & tail symbols
+         *   excluded). Each word must fit into 30-bytes, with MSB first (skip
+         *   B239, B240), covering a time period of 10 seconds. The standard
+         *   followed is European GNSS(Galileo) Signal in Space Interface
+         *   Control Document Issue 1.2.
+         *
+         * - For Galileo I/NAV, each page contains 2 page parts, even and odd, with
+         *   a total of 2x114 = 228 bits, (sync & tail excluded) that must fit
+         *   into 29 bytes, with MSB first (skip B229-B232). The standard followed
+         *   is same as above.
+         *
+         * TODO(b/32022567): Describe this relationship with data to the VTS
+         * via custom annotations and plug in a VTS test to verify that the data
+         * correctly follows the standard.
+         *
+         */
+        vec<uint8_t> data;
+    };
+
+    /*
+     * The callback to report an available fragment of a GNSS navigation messages
+     * from the HAL.
+     *
+     * @param message - The GNSS navigation submessage/subframe representation.
+     */
+     gnssNavigationMessageCb(GnssNavigationMessage message);
+};
diff --git a/gnss/1.0/IGnssNi.hal b/gnss/1.0/IGnssNi.hal
new file mode 100644
index 0000000..c823bf0
--- /dev/null
+++ b/gnss/1.0/IGnssNi.hal
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+import IGnssNiCallback;
+
+/*
+ * Extended interface for Network-initiated (NI) support. This interface is used
+ * to respond to NI notifications originating from the HAL.
+ */
+interface IGnssNi {
+    /*
+     * Registers the callbacks for HAL to use.
+     *
+     * @param callback handle to IGnssNiCallback interface.
+     */
+    setCallback(IGnssNiCallback callback);
+
+    /*
+     * Sends a response to HAL.
+     *
+     * @param notifId An ID generated by HAL to associate NI notifications and
+     * framework responses.
+     * @param userResponse A GNSS Ni response indicating if the notification was
+     * accepted, denied or not responded to.
+     */
+    respond(int32_t notifId, GnssUserResponseType userResponse);
+};
diff --git a/gnss/1.0/IGnssNiCallback.hal b/gnss/1.0/IGnssNiCallback.hal
new file mode 100644
index 0000000..c5fb223
--- /dev/null
+++ b/gnss/1.0/IGnssNiCallback.hal
@@ -0,0 +1,127 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+/* GNSS Network Initiated callback interface. */
+interface IGnssNiCallback {
+    /*
+     * GnssNiType constants
+     */
+    @export(name="", value_prefix="GPS_NI_TYPE_")
+    enum GnssNiType : uint8_t {
+        VOICE           = 1,
+        UMTS_SUPL       = 2,
+        UMTS_CTRL_PLANE = 3
+    };
+
+    /*
+     * GnssNiNotifyFlags constants
+     */
+    @export(name="", value_prefix="GPS_NI_")
+    enum GnssNiNotifyFlags : uint32_t {
+        /** NI requires notification */
+        NEED_NOTIFY      = 0x0001,
+        /** NI requires verification */
+        NEED_VERIFY      = 0x0002,
+        /** NI requires privacy override, no notification/minimal trace */
+        PRIVACY_OVERRIDE = 0x0004,
+    };
+
+    /*
+     * GNSS NI responses, used to define the response in
+     * NI structures
+     */
+    @export(name="", value_prefix="GPS_NI_")
+    enum GnssUserResponseType : uint8_t {
+        RESPONSE_ACCEPT  = 1,
+        RESPONSE_DENY    = 2,
+        RESPONSE_NORESP  = 3,
+    };
+
+    /*
+     * NI data encoding scheme
+     */
+    @export(name="", value_prefix="GPS_")
+    enum GnssNiEncodingType : int32_t {
+        ENC_NONE              = 0,
+        ENC_SUPL_GSM_DEFAULT  = 1,
+        ENC_SUPL_UTF8         = 2,
+        ENC_SUPL_UCS2         = 3,
+        ENC_UNKNOWN           = -1,
+    };
+
+    /** Represents an NI request */
+    struct GnssNiNotification{
+        /*
+         * An ID generated by HAL to associate NI notifications and UI
+         * responses.
+         */
+        int32_t notificationId;
+
+        /*
+         * A type used to distinguish different categories of NI
+         * events, such as VOICE, UMTS_SUPL etc.
+         */
+        GnssNiType niType;
+
+        /*
+         * Notification/verification options, combinations of GnssNiNotifyFlags
+         * constants.
+         */
+        bitfield<GnssNiNotifyFlags> notifyFlags;
+
+        /*
+         * Timeout period to wait for user response.
+         * Set to 0 for no timeout limit. Specified in seconds.
+         */
+        uint32_t timeoutSec;
+
+        /*
+         * Default response when timeout.
+         */
+        GnssUserResponseType defaultResponse;
+
+        /*
+         * String representing the requester of the network inititated location
+         * request.
+         */
+        string requestorId;
+
+        /*
+         * Notification message. String representing the service(for eg. SUPL-service)
+         * who sent the network initiated location request.
+         */
+        string notificationMessage;
+
+        /*
+         * requestorId decoding scheme.
+         */
+        GnssNiEncodingType requestorIdEncoding;
+
+        /*
+         * notificationId decoding scheme
+         */
+        GnssNiEncodingType notificationIdEncoding;
+    };
+
+    /*
+     * Callback with a network initiated request.
+     *
+     * @param notification network initiated request.
+     */
+    niNotifyCb(GnssNiNotification notification);
+};
diff --git a/gnss/1.0/IGnssXtra.hal b/gnss/1.0/IGnssXtra.hal
new file mode 100644
index 0000000..5222fde
--- /dev/null
+++ b/gnss/1.0/IGnssXtra.hal
@@ -0,0 +1,27 @@
+package android.hardware.gnss@1.0;
+import IGnssXtraCallback;
+
+/*
+ * This interface is used by the GNSS HAL to request the framework
+ * to download XTRA data.
+ */
+interface IGnssXtra {
+    /*
+     * Opens the XTRA interface and provides the callback routines
+     * to the implementation of this interface.
+     *
+     * @param callback Handle to the IGnssXtraCallback interface.
+     *
+     * @return success True if the operation is successful.
+     */
+    setCallback(IGnssXtraCallback callback) generates (bool success);
+
+    /*
+     * Inject the downloaded XTRA data into the GNSS receiver.
+     *
+     * @param xtraData GNSS XTRA data.
+     *
+     * @return success True if the operation is successful.
+     */
+    injectXtraData(string xtraData) generates (bool success);
+};
diff --git a/gnss/1.0/IGnssXtraCallback.hal b/gnss/1.0/IGnssXtraCallback.hal
new file mode 100644
index 0000000..42df082
--- /dev/null
+++ b/gnss/1.0/IGnssXtraCallback.hal
@@ -0,0 +1,12 @@
+package android.hardware.gnss@1.0;
+
+/*
+ * This interface is used by the GNSS HAL to request download of XTRA data.
+ */
+interface IGnssXtraCallback {
+   /*
+    * Callback to request the client to download XTRA data. The client should
+    * download XTRA data and inject it by calling injectXtraData().
+    */
+   downloadRequestCb();
+};
diff --git a/gnss/1.0/default/AGnss.cpp b/gnss/1.0/default/AGnss.cpp
new file mode 100644
index 0000000..52fdc26
--- /dev/null
+++ b/gnss/1.0/default/AGnss.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssInterface"
+
+#include "AGnss.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnss::sThreadFuncArgsList;
+sp<IAGnssCallback> AGnss::sAGnssCbIface = nullptr;
+bool AGnss::sInterfaceExists = false;
+
+AGpsCallbacks AGnss::sAGnssCb = {
+    .status_cb = statusCb,
+    .create_thread_cb = createThreadCb
+};
+
+AGnss::AGnss(const AGpsInterface* aGpsIface) : mAGnssIface(aGpsIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnss::~AGnss() {
+    sThreadFuncArgsList.clear();
+}
+
+void AGnss::statusCb(AGpsStatus* status) {
+    if (sAGnssCbIface == nullptr) {
+        ALOGE("%s: AGNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("AGNSS status is invalid");
+        return;
+    }
+
+    /*
+     * Logic based on AGnssStatus processing by GnssLocationProvider. Size of
+     * AGpsStatus is checked for backward compatibility since some devices may
+     * be sending out an older version of AGpsStatus that only supports IPv4.
+     */
+    size_t statusSize = status->size;
+    if (status->size == sizeof(AGpsStatus)) {
+        switch (status->addr.ss_family)
+        {
+            case AF_INET:
+                {
+                    /*
+                     * ss_family indicates IPv4.
+                     */
+                    struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(&(status->addr));
+                    IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+                        .type = static_cast<IAGnssCallback::AGnssType>(status->type),
+                        .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+                        .ipV4Addr = in->sin_addr.s_addr,
+                    };
+
+                    /*
+                     * Callback to client with agnssStatusIpV4Cb.
+                     */
+                    sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+                    break;
+                }
+            case AF_INET6:
+                {
+                    /*
+                     * ss_family indicates IPv6. Callback to client with agnssStatusIpV6Cb.
+                     */
+                    IAGnssCallback::AGnssStatusIpV6 aGnssStatusIpV6;
+
+                    aGnssStatusIpV6.type = static_cast<IAGnssCallback::AGnssType>(status->type);
+                    aGnssStatusIpV6.status = static_cast<IAGnssCallback::AGnssStatusValue>(
+                            status->status);
+
+                    struct sockaddr_in6* in6 = reinterpret_cast<struct sockaddr_in6 *>(
+                            &(status->addr));
+                    memcpy(&(aGnssStatusIpV6.ipV6Addr[0]), in6->sin6_addr.s6_addr,
+                           aGnssStatusIpV6.ipV6Addr.size());
+                    sAGnssCbIface->agnssStatusIpV6Cb(aGnssStatusIpV6);
+                    break;
+                }
+             default:
+                    ALOGE("Invalid ss_family found: %d", status->addr.ss_family);
+        }
+    } else if (statusSize >= sizeof(AGpsStatus_v2)) {
+        AGpsStatus_v2* statusV2 = reinterpret_cast<AGpsStatus_v2*>(status);
+        uint32_t ipV4Addr = statusV2->ipaddr;
+        IAGnssCallback::AGnssStatusIpV4 aGnssStatusIpV4 = {
+            .type = static_cast<IAGnssCallback::AGnssType>(AF_INET),
+            .status = static_cast<IAGnssCallback::AGnssStatusValue>(status->status),
+            /*
+             * For older versions of AGpsStatus, change IP addr to net order. This
+             * was earlier being done in GnssLocationProvider.
+             */
+            .ipV4Addr = htonl(ipV4Addr)
+        };
+        /*
+         * Callback to client with agnssStatusIpV4Cb.
+         */
+        sAGnssCbIface->agnssStatusIpV4Cb(aGnssStatusIpV4);
+    } else {
+        ALOGE("%s: Invalid size for AGPS Status", __func__);
+    }
+}
+
+pthread_t AGnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+/*
+ * Implementation of methods from ::android::hardware::gnss::V1_0::IAGnss follow.
+ */
+Return<void> AGnss::setCallback(const sp<IAGnssCallback>& callback) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssCbIface = callback;
+
+    mAGnssIface->init(&sAGnssCb);
+    return Void();
+}
+
+Return<bool> AGnss::dataConnClosed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_closed() == 0);
+}
+
+Return<bool> AGnss::dataConnFailed()  {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_failed() == 0);
+}
+
+Return<bool> AGnss::setServer(IAGnssCallback::AGnssType type,
+                              const hidl_string& hostname,
+                              int32_t port) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->set_server(static_cast<AGpsType>(type), hostname.c_str(), port) == 0);
+}
+
+Return<bool> AGnss::dataConnOpen(const hidl_string& apn, IAGnss::ApnIpType apnIpType) {
+    if (mAGnssIface == nullptr) {
+        ALOGE("%s: AGnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mAGnssIface->data_conn_open_with_apn_ip_type(apn.c_str(),
+                                                     static_cast<uint16_t>(apnIpType)) == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/AGnss.h b/gnss/1.0/default/AGnss.h
new file mode 100644
index 0000000..2a8eed0
--- /dev/null
+++ b/gnss/1.0/default/AGnss.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnss_H_
+#define android_hardware_gnss_V1_0_AGnss_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnss.h>
+#include <hardware/gps_internal.h>
+#include <hidl/Status.h>
+#include <netinet/in.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnss;
+using ::android::hardware::gnss::V1_0::IAGnssCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS support. Also contains wrapper methods to allow
+ * methods from IAGnssCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct AGnss : public IAGnss {
+    AGnss(const AGpsInterface* agpsIface);
+    ~AGnss();
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnss interface follow.
+     * These declarations were generated from IAGnss.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssCallback>& callback) override;
+    Return<bool> dataConnClosed() override;
+    Return<bool> dataConnFailed() override;
+    Return<bool> setServer(IAGnssCallback::AGnssType type,
+                         const hidl_string& hostname, int32_t port) override;
+    Return<bool> dataConnOpen(const hidl_string& apn,
+                                           IAGnss::ApnIpType apnIpType) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IAGnss base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void statusCb(AGpsStatus* status);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsCallbacks sAGnssCb;
+
+ private:
+    const AGpsInterface* mAGnssIface = nullptr;
+    static sp<IAGnssCallback> sAGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnss_H_
diff --git a/gnss/1.0/default/AGnssRil.cpp b/gnss/1.0/default/AGnssRil.cpp
new file mode 100644
index 0000000..480571d
--- /dev/null
+++ b/gnss/1.0/default/AGnssRil.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_AGnssRilInterface"
+
+#include "AGnssRil.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> AGnssRil::sThreadFuncArgsList;
+sp<IAGnssRilCallback> AGnssRil::sAGnssRilCbIface = nullptr;
+bool AGnssRil::sInterfaceExists = false;
+
+AGpsRilCallbacks AGnssRil::sAGnssRilCb = {
+    .request_setid = AGnssRil::requestSetId,
+    .request_refloc = AGnssRil::requestRefLoc,
+    .create_thread_cb = AGnssRil::createThreadCb
+};
+
+AGnssRil::AGnssRil(const AGpsRilInterface* aGpsRilIface) : mAGnssRilIface(aGpsRilIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+AGnssRil::~AGnssRil() {
+    sThreadFuncArgsList.clear();
+}
+
+void AGnssRil::requestSetId(uint32_t flags) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sAGnssRilCbIface->requestSetIdCb(flags);
+}
+
+void AGnssRil::requestRefLoc(uint32_t /*flags*/) {
+    if (sAGnssRilCbIface == nullptr) {
+        ALOGE("%s: AGNSSRil Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sAGnssRilCbIface->requestRefLocCb();
+}
+
+pthread_t AGnssRil::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+Return<void> AGnssRil::setCallback(const sp<IAGnssRilCallback>& callback)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    sAGnssRilCbIface = callback;
+
+    mAGnssRilIface->init(&sAGnssRilCb);
+    return Void();
+}
+
+Return<void> AGnssRil::setRefLocation(const IAGnssRil::AGnssRefLocation& aGnssRefLocation)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return Void();
+    }
+
+    AGpsRefLocation aGnssRefloc;
+    aGnssRefloc.type = static_cast<uint16_t>(aGnssRefLocation.type);
+
+    auto& cellID = aGnssRefLocation.cellID;
+    aGnssRefloc.u.cellID = {
+        .type = static_cast<uint16_t>(cellID.type),
+        .mcc = cellID.mcc,
+        .mnc = cellID.mnc,
+        .lac = cellID.lac,
+        .cid = cellID.cid,
+        .tac = cellID.tac,
+        .pcid = cellID.pcid
+    };
+
+    mAGnssRilIface->set_ref_location(&aGnssRefloc, sizeof(aGnssRefloc));
+    return Void();
+}
+
+Return<bool> AGnssRil::setSetId(IAGnssRil::SetIDType type, const hidl_string& setid)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->set_set_id(static_cast<uint16_t>(type), setid.c_str());
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkState(bool connected,
+                                          IAGnssRil::NetworkType type,
+                                          bool roaming) {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_state(connected,
+                                         static_cast<int>(type),
+                                         roaming,
+                                         nullptr /* extra_info */);
+    return true;
+}
+
+Return<bool> AGnssRil::updateNetworkAvailability(bool available, const hidl_string& apn)  {
+    if (mAGnssRilIface == nullptr) {
+        ALOGE("%s: AGnssRil interface is unavailable", __func__);
+        return false;
+    }
+
+    mAGnssRilIface->update_network_availability(available, apn.c_str());
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/AGnssRil.h b/gnss/1.0/default/AGnssRil.h
new file mode 100644
index 0000000..6215a9e
--- /dev/null
+++ b/gnss/1.0/default/AGnssRil.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_AGnssRil_H_
+#define android_hardware_gnss_V1_0_AGnssRil_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IAGnssRil.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IAGnssRil;
+using ::android::hardware::gnss::V1_0::IAGnssRilCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for AGNSS RIL support. An Assisted GNSS Radio Interface Layer interface
+ * allows the GNSS chipset to request radio interface layer information from Android platform.
+ * Examples of such information are reference location, unique subscriber ID, phone number string
+ * and network availability changes. Also contains wrapper methods to allow methods from
+ * IAGnssiRilCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct AGnssRil : public IAGnssRil {
+    AGnssRil(const AGpsRilInterface* aGpsRilIface);
+    ~AGnssRil();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IAGnssRil follow.
+     * These declarations were generated from IAGnssRil.hal.
+     */
+    Return<void> setCallback(const sp<IAGnssRilCallback>& callback) override;
+    Return<void> setRefLocation(const IAGnssRil::AGnssRefLocation& agnssReflocation) override;
+    Return<bool> setSetId(IAGnssRil::SetIDType type, const hidl_string& setid) override;
+    Return<bool> updateNetworkState(bool connected,
+                                    IAGnssRil::NetworkType type,
+                                    bool roaming) override;
+    Return<bool> updateNetworkAvailability(bool available, const hidl_string& apn) override;
+    static void requestSetId(uint32_t flags);
+    static void requestRefLoc(uint32_t flags);
+
+    /*
+     * Callback method to be passed into the conventional GNSS HAL by the default
+     * implementation. This method is not part of the IAGnssRil base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static AGpsRilCallbacks sAGnssRilCb;
+
+ private:
+    const AGpsRilInterface* mAGnssRilIface = nullptr;
+    static sp<IAGnssRilCallback> sAGnssRilCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_AGnssRil_H_
diff --git a/gnss/1.0/default/Android.mk b/gnss/1.0/default/Android.mk
new file mode 100644
index 0000000..a6f73f2
--- /dev/null
+++ b/gnss/1.0/default/Android.mk
@@ -0,0 +1,54 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.gnss@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    ThreadCreationWrapper.cpp \
+    AGnss.cpp \
+    AGnssRil.cpp \
+    Gnss.cpp \
+    GnssBatching.cpp \
+    GnssDebug.cpp \
+    GnssGeofencing.cpp \
+    GnssMeasurement.cpp \
+    GnssNavigationMessage.cpp \
+    GnssNi.cpp \
+    GnssXtra.cpp \
+    GnssConfiguration.cpp \
+    GnssUtils.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    android.hardware.gnss@1.0 \
+    libhardware
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.gnss@1.0-service
+LOCAL_INIT_RC := android.hardware.gnss@1.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.gnss@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/gnss/1.0/default/Gnss.cpp b/gnss/1.0/default/Gnss.cpp
new file mode 100644
index 0000000..19e22c2
--- /dev/null
+++ b/gnss/1.0/default/Gnss.cpp
@@ -0,0 +1,580 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssInterface"
+
+#include "Gnss.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> Gnss::sThreadFuncArgsList;
+sp<IGnssCallback> Gnss::sGnssCbIface = nullptr;
+bool Gnss::sInterfaceExists = false;
+
+GpsCallbacks Gnss::sGnssCb = {
+    .size = sizeof(GpsCallbacks),
+    .location_cb = locationCb,
+    .status_cb = statusCb,
+    .sv_status_cb = gpsSvStatusCb,
+    .nmea_cb = nmeaCb,
+    .set_capabilities_cb = setCapabilitiesCb,
+    .acquire_wakelock_cb = acquireWakelockCb,
+    .release_wakelock_cb = releaseWakelockCb,
+    .create_thread_cb = createThreadCb,
+    .request_utc_time_cb = requestUtcTimeCb,
+    .set_system_info_cb = setSystemInfoCb,
+    .gnss_sv_status_cb = gnssSvStatusCb,
+};
+
+Gnss::Gnss(gps_device_t* gnssDevice) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+
+    if (gnssDevice == nullptr) {
+        ALOGE("%s: Invalid device_t handle", __func__);
+        return;
+    }
+
+    mGnssIface = gnssDevice->get_gps_interface(gnssDevice);
+}
+
+Gnss::~Gnss() {
+    sThreadFuncArgsList.clear();
+}
+
+void Gnss::locationCb(GpsLocation* location) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s: Invalid location from GNSS HAL", __func__);
+        return;
+    }
+
+    android::hardware::gnss::V1_0::GnssLocation gnssLocation = convertToGnssLocation(location);
+    sGnssCbIface->gnssLocationCb(gnssLocation);
+}
+
+void Gnss::statusCb(GpsStatus* gnssStatus) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (gnssStatus == nullptr) {
+        ALOGE("%s: Invalid GpsStatus from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssCallback::GnssStatusValue status =
+            static_cast<IGnssCallback::GnssStatusValue>(gnssStatus->status);
+
+    sGnssCbIface->gnssStatusCb(status);
+}
+
+void Gnss::gnssSvStatusCb(GnssSvStatus* status) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (status == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = status->num_svs;
+
+    if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
+        ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+        svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
+    }
+
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        auto svInfo = status->gnss_sv_list[i];
+        IGnssCallback::GnssSvInfo gnssSvInfo = {
+            .svid = svInfo.svid,
+            .constellation = static_cast<android::hardware::gnss::V1_0::GnssConstellationType>(
+                    svInfo.constellation),
+            .cN0Dbhz = svInfo.c_n0_dbhz,
+            .elevationDegrees = svInfo.elevation,
+            .azimuthDegrees = svInfo.azimuth,
+            .svFlag = svInfo.flags,
+            // Older chipsets do not provide carrier frequency, hence HAS_CARRIER_FREQUENCY flag
+            // is not set and the carrierFrequencyHz field is set to zero
+            .carrierFrequencyHz = 0
+        };
+        svStatus.gnssSvList[i] = gnssSvInfo;
+    }
+
+    sGnssCbIface->gnssSvStatusCb(svStatus);
+}
+
+/*
+ * This enum is used by gpsSvStatusCb() method below to convert GpsSvStatus
+ * to GnssSvStatus for backward compatibility. It is only used by the default
+ * implementation and is not part of the GNSS interface.
+ */
+enum SvidValues : uint16_t {
+    GLONASS_SVID_OFFSET = 64,
+    GLONASS_SVID_COUNT = 24,
+    BEIDOU_SVID_OFFSET = 200,
+    BEIDOU_SVID_COUNT = 35,
+    SBAS_SVID_MIN = 33,
+    SBAS_SVID_MAX = 64,
+    SBAS_SVID_ADD = 87,
+    QZSS_SVID_MIN = 193,
+    QZSS_SVID_MAX = 200
+};
+
+/*
+ * The following code that converts GpsSvStatus to GnssSvStatus is moved here from
+ * GnssLocationProvider. GnssLocationProvider does not require it anymore since GpsSvStatus is
+ * being deprecated and is no longer part of the GNSS interface.
+ */
+void Gnss::gpsSvStatusCb(GpsSvStatus* svInfo) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (svInfo == nullptr) {
+        ALOGE("Invalid status from GNSS HAL %s", __func__);
+        return;
+    }
+
+    IGnssCallback::GnssSvStatus svStatus;
+    svStatus.numSvs = svInfo->num_svs;
+    /*
+     * Clamp the list size since GnssSvStatus can support a maximum of
+     * GnssMax::SVS_COUNT entries.
+     */
+    if (svStatus.numSvs > static_cast<uint32_t>(GnssMax::SVS_COUNT)) {
+        ALOGW("Too many satellites %zd. Clamps to %d.", svStatus.numSvs, GnssMax::SVS_COUNT);
+        svStatus.numSvs = static_cast<uint32_t>(GnssMax::SVS_COUNT);
+    }
+
+    uint32_t ephemerisMask = svInfo->ephemeris_mask;
+    uint32_t almanacMask = svInfo->almanac_mask;
+    uint32_t usedInFixMask = svInfo->used_in_fix_mask;
+    /*
+     * Conversion from GpsSvInfo to IGnssCallback::GnssSvInfo happens below.
+     */
+    for (size_t i = 0; i < svStatus.numSvs; i++) {
+        IGnssCallback::GnssSvInfo& info = svStatus.gnssSvList[i];
+        info.svid = svInfo->sv_list[i].prn;
+        if (info.svid >= 1 && info.svid <= 32) {
+            info.constellation = GnssConstellationType::GPS;
+        } else if (info.svid > GLONASS_SVID_OFFSET &&
+                   info.svid <= GLONASS_SVID_OFFSET + GLONASS_SVID_COUNT) {
+            info.constellation = GnssConstellationType::GLONASS;
+            info.svid -= GLONASS_SVID_OFFSET;
+        } else if (info.svid > BEIDOU_SVID_OFFSET &&
+                 info.svid <= BEIDOU_SVID_OFFSET + BEIDOU_SVID_COUNT) {
+            info.constellation = GnssConstellationType::BEIDOU;
+            info.svid -= BEIDOU_SVID_OFFSET;
+        } else if (info.svid >= SBAS_SVID_MIN && info.svid <= SBAS_SVID_MAX) {
+            info.constellation = GnssConstellationType::SBAS;
+            info.svid += SBAS_SVID_ADD;
+        } else if (info.svid >= QZSS_SVID_MIN && info.svid <= QZSS_SVID_MAX) {
+            info.constellation = GnssConstellationType::QZSS;
+        } else {
+            ALOGD("Unknown constellation type with Svid = %d.", info.svid);
+            info.constellation = GnssConstellationType::UNKNOWN;
+        }
+
+        info.cN0Dbhz = svInfo->sv_list[i].snr;
+        info.elevationDegrees = svInfo->sv_list[i].elevation;
+        info.azimuthDegrees = svInfo->sv_list[i].azimuth;
+        // TODO: b/31702236
+        info.svFlag = static_cast<uint8_t>(IGnssCallback::GnssSvFlags::NONE);
+
+        /*
+         * Only GPS info is valid for these fields, as these masks are just 32
+         * bits, by GPS prn.
+         */
+        if (info.constellation == GnssConstellationType::GPS) {
+            int32_t svidMask = (1 << (info.svid - 1));
+            if ((ephemerisMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_EPHEMERIS_DATA;
+            }
+            if ((almanacMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::HAS_ALMANAC_DATA;
+            }
+            if ((usedInFixMask & svidMask) != 0) {
+                info.svFlag |= IGnssCallback::GnssSvFlags::USED_IN_FIX;
+            }
+        }
+    }
+
+    sGnssCbIface->gnssSvStatusCb(svStatus);
+}
+
+void Gnss::nmeaCb(GpsUtcTime timestamp, const char* nmea, int length) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    android::hardware::hidl_string nmeaString;
+    nmeaString.setToExternal(nmea, length);
+    sGnssCbIface->gnssNmeaCb(timestamp, nmeaString);
+}
+
+void Gnss::setCapabilitiesCb(uint32_t capabilities) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sGnssCbIface->gnssSetCapabilitesCb(capabilities);
+}
+
+void Gnss::acquireWakelockCb() {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sGnssCbIface->gnssAcquireWakelockCb();
+}
+
+void Gnss::releaseWakelockCb() {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sGnssCbIface->gnssReleaseWakelockCb();
+}
+
+void Gnss::requestUtcTimeCb() {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sGnssCbIface->gnssRequestTimeCb();
+}
+
+pthread_t Gnss::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void Gnss::setSystemInfoCb(const LegacyGnssSystemInfo* info) {
+    if (sGnssCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (info == nullptr) {
+        ALOGE("Invalid GnssSystemInfo from GNSS HAL %s", __func__);
+        return;
+    }
+
+    IGnssCallback::GnssSystemInfo gnssInfo = {
+        .yearOfHw = info->year_of_hw
+    };
+
+    sGnssCbIface->gnssSetSystemInfoCb(gnssInfo);
+}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+Return<bool> Gnss::setCallback(const sp<IGnssCallback>& callback)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    sGnssCbIface = callback;
+
+    return (mGnssIface->init(&sGnssCb) == 0);
+}
+
+Return<bool> Gnss::start()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->start() == 0);
+}
+
+Return<bool> Gnss::stop()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->stop() == 0);
+}
+
+Return<void> Gnss::cleanup()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->cleanup();
+    }
+    return Void();
+}
+
+Return<bool> Gnss::injectLocation(double latitudeDegrees,
+                                  double longitudeDegrees,
+                                  float accuracyMeters)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_location(latitudeDegrees, longitudeDegrees, accuracyMeters) == 0);
+}
+
+Return<bool> Gnss::injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                              int32_t uncertaintyMs) {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->inject_time(timeMs, timeReferenceMs, uncertaintyMs) == 0);
+}
+
+Return<void> Gnss::deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        mGnssIface->delete_aiding_data(static_cast<GpsAidingData>(aidingDataFlags));
+    }
+    return Void();
+}
+
+Return<bool> Gnss::setPositionMode(IGnss::GnssPositionMode mode,
+                                   IGnss::GnssPositionRecurrence recurrence,
+                                   uint32_t minIntervalMs,
+                                   uint32_t preferredAccuracyMeters,
+                                   uint32_t preferredTimeMs)  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+        return false;
+    }
+
+    return (mGnssIface->set_position_mode(static_cast<GpsPositionMode>(mode),
+                                          static_cast<GpsPositionRecurrence>(recurrence),
+                                          minIntervalMs,
+                                          preferredAccuracyMeters,
+                                          preferredTimeMs) == 0);
+}
+
+Return<sp<IAGnssRil>> Gnss::getExtensionAGnssRil()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
+                mGnssIface->get_extension(AGPS_RIL_INTERFACE));
+        if (agpsRilIface == nullptr) {
+            ALOGE("%s GnssRil interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssRil = new AGnssRil(agpsRilIface);
+        }
+    }
+    return mGnssRil;
+}
+
+Return<sp<IGnssConfiguration>> Gnss::getExtensionGnssConfiguration()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GnssConfigurationInterface* gnssConfigIface =
+                static_cast<const GnssConfigurationInterface*>(
+                        mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
+
+        if (gnssConfigIface == nullptr) {
+            ALOGE("%s GnssConfiguration interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssConfig = new GnssConfiguration(gnssConfigIface);
+        }
+    }
+    return mGnssConfig;
+}
+Return<sp<IGnssGeofencing>> Gnss::getExtensionGnssGeofencing()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsGeofencingInterface* gpsGeofencingIface =
+                static_cast<const GpsGeofencingInterface*>(
+                        mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
+
+        if (gpsGeofencingIface == nullptr) {
+            ALOGE("%s GnssGeofencing interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
+        }
+    }
+
+    return mGnssGeofencingIface;
+}
+
+Return<sp<IAGnss>> Gnss::getExtensionAGnss()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
+                mGnssIface->get_extension(AGPS_INTERFACE));
+        if (agpsIface == nullptr) {
+            ALOGE("%s AGnss interface not implemented by GNSS HAL", __func__);
+        } else {
+            mAGnssIface = new AGnss(agpsIface);
+        }
+    }
+    return mAGnssIface;
+}
+
+Return<sp<IGnssNi>> Gnss::getExtensionGnssNi()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
+                mGnssIface->get_extension(GPS_NI_INTERFACE));
+        if (gpsNiIface == nullptr) {
+            ALOGE("%s GnssNi interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssNi = new GnssNi(gpsNiIface);
+        }
+    }
+    return mGnssNi;
+}
+
+Return<sp<IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsMeasurementInterface* gpsMeasurementIface =
+                static_cast<const GpsMeasurementInterface*>(
+                        mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
+
+        if (gpsMeasurementIface == nullptr) {
+            ALOGE("%s GnssMeasurement interface not implemented by GNSS HAL", __func__);
+        } else {
+            mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
+        }
+    }
+    return mGnssMeasurement;
+}
+
+Return<sp<IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface =
+                static_cast<const GpsNavigationMessageInterface*>(
+                        mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
+
+        if (gpsNavigationMessageIface == nullptr) {
+            ALOGE("%s GnssNavigationMessage interface not implemented by GNSS HAL",
+                  __func__);
+        } else {
+            mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
+        }
+    }
+
+    return mGnssNavigationMessage;
+}
+
+Return<sp<IGnssXtra>> Gnss::getExtensionXtra()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsXtraInterface* gpsXtraIface = static_cast<const GpsXtraInterface*>(
+                mGnssIface->get_extension(GPS_XTRA_INTERFACE));
+
+        if (gpsXtraIface == nullptr) {
+            ALOGE("%s GnssXtra interface not implemented by HAL", __func__);
+        } else {
+            mGnssXtraIface = new GnssXtra(gpsXtraIface);
+        }
+    }
+
+    return mGnssXtraIface;
+}
+
+Return<sp<IGnssDebug>> Gnss::getExtensionGnssDebug()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        const GpsDebugInterface* gpsDebugIface = static_cast<const GpsDebugInterface*>(
+                mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
+
+        if (gpsDebugIface == nullptr) {
+            ALOGE("%s: GnssDebug interface is not implemented by HAL", __func__);
+        } else {
+            mGnssDebug = new GnssDebug(gpsDebugIface);
+        }
+    }
+
+    return mGnssDebug;
+}
+
+Return<sp<IGnssBatching>> Gnss::getExtensionGnssBatching()  {
+    if (mGnssIface == nullptr) {
+        ALOGE("%s: Gnss interface is unavailable", __func__);
+    } else {
+        // TODO(b/34133439): actually get an flpLocationIface
+        const FlpLocationInterface* flpLocationIface = nullptr;
+
+        if (flpLocationIface == nullptr) {
+            ALOGE("%s: GnssBatching interface is not implemented by HAL", __func__);
+        } else {
+            mGnssBatching = new GnssBatching(flpLocationIface);
+        }
+    }
+
+    return mGnssBatching;
+}
+
+IGnss* HIDL_FETCH_IGnss(const char* hal) {
+    hw_module_t* module;
+    IGnss* iface = nullptr;
+    int err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+
+    if (err == 0) {
+        hw_device_t* device;
+        err = module->methods->open(module, GPS_HARDWARE_MODULE_ID, &device);
+        if (err == 0) {
+            iface = new Gnss(reinterpret_cast<gps_device_t*>(device));
+        } else {
+            ALOGE("gnssDevice open %s failed: %d", hal, err);
+        }
+    } else {
+      ALOGE("gnss hw_get_module %s failed: %d", hal, err);
+    }
+    return iface;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/Gnss.h b/gnss/1.0/default/Gnss.h
new file mode 100644
index 0000000..36947c1
--- /dev/null
+++ b/gnss/1.0/default/Gnss.h
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_Gnss_H_
+#define android_hardware_gnss_V1_0_Gnss_H_
+
+#include <AGnss.h>
+#include <AGnssRil.h>
+#include <GnssBatching.h>
+#include <GnssConfiguration.h>
+#include <GnssDebug.h>
+#include <GnssGeofencing.h>
+#include <GnssMeasurement.h>
+#include <GnssNavigationMessage.h>
+#include <GnssNi.h>
+#include <GnssXtra.h>
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <hardware/fused_location.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssSystemInfo = ::GnssSystemInfo;
+
+/*
+ * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
+ * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct Gnss : public IGnss {
+    // TODO: Add flp_device_t, either in ctor, or later attach?
+    Gnss(gps_device_t* gnss_device);
+    ~Gnss();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnss follow.
+     * These declarations were generated from Gnss.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssCallback>& callback)  override;
+    Return<bool> start()  override;
+    Return<bool> stop()  override;
+    Return<void> cleanup()  override;
+    Return<bool> injectLocation(double latitudeDegrees,
+                                double longitudeDegrees,
+                                float accuracyMeters)  override;
+    Return<bool> injectTime(int64_t timeMs,
+                            int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<void> deleteAidingData(IGnss::GnssAidingData aidingDataFlags)  override;
+    Return<bool> setPositionMode(IGnss::GnssPositionMode mode,
+                                 IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs,
+                                 uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs)  override;
+    Return<sp<IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<IAGnss>> getExtensionAGnss() override;
+    Return<sp<IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+    Return<sp<IGnssXtra>> getExtensionXtra() override;
+    Return<sp<IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<IGnssBatching>> getExtensionGnssBatching() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnss base class.
+     */
+    static void locationCb(GpsLocation* location);
+    static void statusCb(GpsStatus* gnss_status);
+    static void nmeaCb(GpsUtcTime timestamp, const char* nmea, int length);
+    static void setCapabilitiesCb(uint32_t capabilities);
+    static void acquireWakelockCb();
+    static void releaseWakelockCb();
+    static void requestUtcTimeCb();
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssSvStatusCb(GnssSvStatus* status);
+    /*
+     * Deprecated callback added for backward compatibility to devices that do
+     * not support GnssSvStatus.
+     */
+    static void gpsSvStatusCb(GpsSvStatus* status);
+    static void setSystemInfoCb(const LegacyGnssSystemInfo* info);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsCallbacks sGnssCb;
+
+ private:
+    sp<GnssXtra> mGnssXtraIface = nullptr;
+    sp<AGnssRil> mGnssRil = nullptr;
+    sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
+    sp<AGnss> mAGnssIface = nullptr;
+    sp<GnssNi> mGnssNi = nullptr;
+    sp<GnssMeasurement> mGnssMeasurement = nullptr;
+    sp<GnssNavigationMessage> mGnssNavigationMessage = nullptr;
+    sp<GnssDebug> mGnssDebug = nullptr;
+    sp<GnssConfiguration> mGnssConfig = nullptr;
+    sp<GnssBatching> mGnssBatching = nullptr;
+    const GpsInterface* mGnssIface = nullptr;
+    static sp<IGnssCallback> sGnssCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_Gnss_H_
diff --git a/gnss/1.0/default/GnssBatching.cpp b/gnss/1.0/default/GnssBatching.cpp
new file mode 100644
index 0000000..404b5da
--- /dev/null
+++ b/gnss/1.0/default/GnssBatching.cpp
@@ -0,0 +1,48 @@
+#include "GnssBatching.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssBatching::GnssBatching(const FlpLocationInterface* flpLocationIface) :
+    mFlpLocationIface(flpLocationIface) {}
+
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+Return<bool> GnssBatching::init(const sp<IGnssBatchingCallback>& callback) {
+    // TODO(b/34133439) implement
+    return false;
+}
+
+Return<uint16_t> GnssBatching::getBatchSize() {
+    // TODO(b/34133439) implement
+    return 0;
+}
+
+Return<bool> GnssBatching::start(const IGnssBatching::Options& options) {
+    // TODO(b/34133439) implement
+    return false;
+}
+
+Return<void> GnssBatching::flush() {
+    // TODO(b/34133439) implement
+    return Void();
+}
+
+Return<bool> GnssBatching::stop() {
+    // TODO(b/34133439) implement
+    return false;
+}
+
+Return<void> GnssBatching::cleanup() {
+    // TODO(b/34133439) implement
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssBatching.h b/gnss/1.0/default/GnssBatching.h
new file mode 100644
index 0000000..ac3aa99
--- /dev/null
+++ b/gnss/1.0/default/GnssBatching.h
@@ -0,0 +1,50 @@
+#ifndef ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+#define ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <hardware/fused_location.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssBatching;
+using ::android::hardware::gnss::V1_0::IGnssBatchingCallback;
+using ::android::hidl::base::V1_0::IBase;
+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;
+
+struct GnssBatching : public IGnssBatching {
+    GnssBatching(const FlpLocationInterface* flpLocationIface);
+
+    // Methods from ::android::hardware::gnss::V1_0::IGnssBatching follow.
+    Return<bool> init(const sp<IGnssBatchingCallback>& callback) override;
+    Return<uint16_t> getBatchSize() override;
+    Return<bool> start(const IGnssBatching::Options& options ) override;
+    Return<void> flush() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+
+ private:
+    const FlpLocationInterface* mFlpLocationIface = nullptr;
+};
+
+extern "C" IGnssBatching* HIDL_FETCH_IGnssBatching(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V1_0_GNSSBATCHING_H
diff --git a/gnss/1.0/default/GnssConfiguration.cpp b/gnss/1.0/default/GnssConfiguration.cpp
new file mode 100644
index 0000000..0c1aa86
--- /dev/null
+++ b/gnss/1.0/default/GnssConfiguration.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssConfigurationInterface"
+
+#include <log/log.h>
+
+#include "GnssConfiguration.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssConfiguration::GnssConfiguration(const GnssConfigurationInterface* gnssConfigInfc)
+    : mGnssConfigIface(gnssConfigInfc) {}
+
+// Methods from ::android::hardware::gps::V1_0::IGnssConfiguration follow.
+Return<bool> GnssConfiguration::setSuplEs(bool enabled)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_ES=" + std::to_string(enabled ? 1 : 0) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplVersion(uint32_t version)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_VER=" + std::to_string(version) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+
+    return true;
+}
+
+Return<bool> GnssConfiguration::setSuplMode(uint8_t mode)  {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "SUPL_MODE=" + std::to_string(mode) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setLppProfile(uint8_t lppProfile) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "LPP_PROFILE=" + std::to_string(lppProfile) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGlonassPositioningProtocol(uint8_t protocol) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "A_GLONASS_POS_PROTOCOL_SELECT=" +
+            std::to_string(protocol) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setGpsLock(uint8_t lock) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "GPS_LOCK=" + std::to_string(lock) + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+Return<bool> GnssConfiguration::setEmergencySuplPdn(bool enabled) {
+    if (mGnssConfigIface == nullptr) {
+        ALOGE("%s: GNSS Configuration interface is not available.", __func__);
+        return false;
+    }
+
+    std::string config = "USE_EMERGENCY_PDN_FOR_EMERGENCY_SUPL=" + std::to_string(enabled ? 1 : 0)
+            + "\n";
+    mGnssConfigIface->configuration_update(config.c_str(), config.size());
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssConfiguration.h b/gnss/1.0/default/GnssConfiguration.h
new file mode 100644
index 0000000..a6eca88
--- /dev/null
+++ b/gnss/1.0/default/GnssConfiguration.h
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+
+#ifndef android_hardware_gnss_V1_0_GnssConfiguration_H_
+#define android_hardware_gnss_V1_0_GnssConfiguration_H_
+
+#include <android/hardware/gnss/1.0/IGnssConfiguration.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssConfiguration;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for passing GNSS configuration info from platform to HAL.
+ */
+struct GnssConfiguration : public IGnssConfiguration {
+    GnssConfiguration(const GnssConfigurationInterface* gnssConfigIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
+     * These declarations were generated from IGnssConfiguration.hal.
+     */
+    Return<bool> setSuplVersion(uint32_t version) override;
+    Return<bool> setSuplMode(uint8_t mode) override;
+    Return<bool> setSuplEs(bool enabled) override;
+    Return<bool> setLppProfile(uint8_t lppProfile) override;
+    Return<bool> setGlonassPositioningProtocol(uint8_t protocol) override;
+    Return<bool> setEmergencySuplPdn(bool enable) override;
+    Return<bool> setGpsLock(uint8_t lock) override;
+
+ private:
+    const GnssConfigurationInterface* mGnssConfigIface = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssConfiguration_H_
diff --git a/gnss/1.0/default/GnssDebug.cpp b/gnss/1.0/default/GnssDebug.cpp
new file mode 100644
index 0000000..cfc38ca
--- /dev/null
+++ b/gnss/1.0/default/GnssDebug.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssDebugInterface"
+
+#include <log/log.h>
+
+#include "GnssDebug.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+GnssDebug::GnssDebug(const GpsDebugInterface* gpsDebugIface) : mGnssDebugIface(gpsDebugIface) {}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+Return<void> GnssDebug::getDebugData(getDebugData_cb _hidl_cb)  {
+    /*
+     * This is a new interface and hence there is no way to retrieve the
+     * debug data from the HAL.
+     */
+    DebugData data = {};
+
+    _hidl_cb(data);
+
+    /*
+     * Log the debug data sent from the conventional Gnss HAL. This code is
+     * moved here from GnssLocationProvider.
+     */
+    if (mGnssDebugIface) {
+        char buffer[kMaxDebugStrLen + 1];
+        size_t length = mGnssDebugIface->get_internal_state(buffer, kMaxDebugStrLen);
+        length = std::max(length, kMaxDebugStrLen);
+        buffer[length] = '\0';
+        ALOGD("Gnss Debug Data: %s", buffer);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssDebug.h b/gnss/1.0/default/GnssDebug.h
new file mode 100644
index 0000000..9a17dde
--- /dev/null
+++ b/gnss/1.0/default/GnssDebug.h
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssDebug_H_
+#define android_hardware_gnss_V1_0_GnssDebug_H_
+
+#include <android/hardware/gnss/1.0/IGnssDebug.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssDebug;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/* Interface for GNSS Debug support. */
+struct GnssDebug : public IGnssDebug {
+    GnssDebug(const GpsDebugInterface* gpsDebugIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
+     * These declarations were generated from IGnssDebug.hal.
+     */
+    Return<void> getDebugData(getDebugData_cb _hidl_cb)  override;
+
+ private:
+    /*
+     * Constant added for backward compatibility to conventional GPS Hals which
+     * returned a debug string.
+     */
+    const size_t kMaxDebugStrLen = 2047;
+    const GpsDebugInterface* mGnssDebugIface = nullptr;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssDebug_H_
diff --git a/gnss/1.0/default/GnssGeofencing.cpp b/gnss/1.0/default/GnssGeofencing.cpp
new file mode 100644
index 0000000..f42de42
--- /dev/null
+++ b/gnss/1.0/default/GnssGeofencing.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHal_GnssGeofencing"
+
+#include "GnssGeofencing.h"
+#include <GnssUtils.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssGeofencing::sThreadFuncArgsList;
+sp<IGnssGeofenceCallback> GnssGeofencing::mGnssGeofencingCbIface = nullptr;
+bool GnssGeofencing::sInterfaceExists = false;
+
+GpsGeofenceCallbacks GnssGeofencing::sGnssGfCb = {
+    .geofence_transition_callback = gnssGfTransitionCb,
+    .geofence_status_callback = gnssGfStatusCb,
+    .geofence_add_callback = gnssGfAddCb,
+    .geofence_remove_callback = gnssGfRemoveCb,
+    .geofence_pause_callback = gnssGfPauseCb,
+    .geofence_resume_callback = gnssGfResumeCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssGeofencing::GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface)
+    : mGnssGeofencingIface(gpsGeofencingIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssGeofencing::~GnssGeofencing() {
+    sThreadFuncArgsList.clear();
+}
+void GnssGeofencing::gnssGfTransitionCb(int32_t geofenceId,
+                                        GpsLocation* location,
+                                        int32_t transition,
+                                        GpsUtcTime timestamp) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (location == nullptr) {
+        ALOGE("%s : Invalid location from GNSS HAL", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation = convertToGnssLocation(location);
+    mGnssGeofencingCbIface->gnssGeofenceTransitionCb(
+            geofenceId,
+            gnssLocation,
+            static_cast<IGnssGeofenceCallback::GeofenceTransition>(transition),
+            timestamp);
+}
+
+void GnssGeofencing::gnssGfStatusCb(int32_t status, GpsLocation* location) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    GnssLocation gnssLocation;
+
+    if (location != nullptr) {
+        gnssLocation = convertToGnssLocation(location);
+    } else {
+        gnssLocation = {};
+    }
+
+    mGnssGeofencingCbIface->gnssGeofenceStatusCb(
+            static_cast<IGnssGeofenceCallback::GeofenceAvailability>(status), gnssLocation);
+}
+
+void GnssGeofencing::gnssGfAddCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    mGnssGeofencingCbIface->gnssGeofenceAddCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+}
+
+void GnssGeofencing::gnssGfRemoveCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    mGnssGeofencingCbIface->gnssGeofenceRemoveCb(
+      geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+}
+
+void GnssGeofencing::gnssGfPauseCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    mGnssGeofencingCbIface->gnssGeofencePauseCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+}
+
+void GnssGeofencing::gnssGfResumeCb(int32_t geofenceId, int32_t status) {
+    if (mGnssGeofencingCbIface == nullptr) {
+        ALOGE("%s: GNSS Geofence Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    mGnssGeofencingCbIface->gnssGeofenceResumeCb(
+            geofenceId, static_cast<IGnssGeofenceCallback::GeofenceStatus>(status));
+}
+
+pthread_t GnssGeofencing::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+Return<void> GnssGeofencing::setCallback(const sp<IGnssGeofenceCallback>& callback)  {
+    mGnssGeofencingCbIface = callback;
+
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->init(&sGnssGfCb);
+    }
+
+    return Void();
+}
+
+Return<void> GnssGeofencing::addGeofence(
+        int32_t geofenceId,
+        double latitudeDegrees,
+        double longitudeDegrees,
+        double radiusMeters,
+        IGnssGeofenceCallback::GeofenceTransition lastTransition,
+        int32_t monitorTransitions,
+        uint32_t notificationResponsivenessMs,
+        uint32_t unknownTimerMs)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+        return Void();
+    } else {
+        mGnssGeofencingIface->add_geofence_area(
+                geofenceId,
+                latitudeDegrees,
+                longitudeDegrees,
+                radiusMeters,
+                static_cast<int32_t>(lastTransition),
+                monitorTransitions,
+                notificationResponsivenessMs,
+                unknownTimerMs);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::pauseGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->pause_geofence(geofenceId);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->resume_geofence(geofenceId, monitorTransitions);
+    }
+    return Void();
+}
+
+Return<void> GnssGeofencing::removeGeofence(int32_t geofenceId)  {
+    if (mGnssGeofencingIface == nullptr) {
+        ALOGE("%s: GnssGeofencing interface is not available", __func__);
+    } else {
+        mGnssGeofencingIface->remove_geofence_area(geofenceId);
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssGeofencing.h b/gnss/1.0/default/GnssGeofencing.h
new file mode 100644
index 0000000..124b893
--- /dev/null
+++ b/gnss/1.0/default/GnssGeofencing.h
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssGeofencing_H_
+#define android_hardware_gnss_V1_0_GnssGeofencing_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssGeofencing.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssGeofenceCallback;
+using ::android::hardware::gnss::V1_0::IGnssGeofencing;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Interface for GNSS Geofencing support. It also contains wrapper methods to allow
+ * methods from IGnssGeofenceCallback interface to be passed into the
+ * conventional implementation of the GNSS HAL.
+ */
+struct GnssGeofencing : public IGnssGeofencing {
+    GnssGeofencing(const GpsGeofencingInterface* gpsGeofencingIface);
+    ~GnssGeofencing();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssGeofencing follow.
+     * These declarations were generated from IGnssGeofencing.hal.
+     */
+    Return<void> setCallback(const sp<IGnssGeofenceCallback>& callback)  override;
+    Return<void> addGeofence(int32_t geofenceId,
+                             double latitudeDegrees,
+                             double longitudeDegrees,
+                             double radiusMeters,
+                             IGnssGeofenceCallback::GeofenceTransition lastTransition,
+                             int32_t monitorTransitions,
+                             uint32_t notificationResponsivenessMs,
+                             uint32_t unknownTimerMs)  override;
+
+    Return<void> pauseGeofence(int32_t geofenceId)  override;
+    Return<void> resumeGeofence(int32_t geofenceId, int32_t monitorTransitions)  override;
+    Return<void> removeGeofence(int32_t geofenceId)  override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssGeofencing base class.
+     */
+    static void gnssGfTransitionCb(int32_t geofence_id, GpsLocation* location,
+                                   int32_t transition, GpsUtcTime timestamp);
+    static void gnssGfStatusCb(int32_t status, GpsLocation* last_location);
+    static void gnssGfAddCb(int32_t geofence_id, int32_t status);
+    static void gnssGfRemoveCb(int32_t geofence_id, int32_t status);
+    static void gnssGfPauseCb(int32_t geofence_id, int32_t status);
+    static void gnssGfResumeCb(int32_t geofence_id, int32_t status);
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsGeofenceCallbacks sGnssGfCb;
+
+ private:
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static sp<IGnssGeofenceCallback> mGnssGeofencingCbIface;
+    const GpsGeofencingInterface* mGnssGeofencingIface = nullptr;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssGeofencing_H_
diff --git a/gnss/1.0/default/GnssMeasurement.cpp b/gnss/1.0/default/GnssMeasurement.cpp
new file mode 100644
index 0000000..67f6d8d
--- /dev/null
+++ b/gnss/1.0/default/GnssMeasurement.cpp
@@ -0,0 +1,255 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssMeasurementInterface"
+
+#include "GnssMeasurement.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssMeasurementCallback> GnssMeasurement::sGnssMeasureCbIface = nullptr;
+GpsMeasurementCallbacks GnssMeasurement::sGnssMeasurementCbs = {
+    .size = sizeof(GpsMeasurementCallbacks),
+    .measurement_callback = gpsMeasurementCb,
+    .gnss_measurement_callback = gnssMeasurementCb
+};
+
+GnssMeasurement::GnssMeasurement(const GpsMeasurementInterface* gpsMeasurementIface)
+    : mGnssMeasureIface(gpsMeasurementIface) {}
+
+void GnssMeasurement::gnssMeasurementCb(LegacyGnssData* legacyGnssData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (legacyGnssData == nullptr) {
+        ALOGE("%s: Invalid GnssData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    gnssData.measurementCount = std::min(legacyGnssData->measurement_count,
+                                         static_cast<size_t>(GnssMax::SVS_COUNT));
+
+    for (size_t i = 0; i < gnssData.measurementCount; i++) {
+        auto entry = legacyGnssData->measurements[i];
+        auto state = static_cast<GnssMeasurementState>(entry.state);
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_TOW_KNOWN;
+        }
+        if (state & IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_DECODED) {
+          state |= IGnssMeasurementCallback::GnssMeasurementState::STATE_GLO_TOD_KNOWN;
+        }
+        gnssData.measurements[i] = {
+            .flags = entry.flags,
+            .svid = entry.svid,
+            .constellation = static_cast<GnssConstellationType>(entry.constellation),
+            .timeOffsetNs = entry.time_offset_ns,
+            .state = state,
+            .receivedSvTimeInNs = entry.received_sv_time_in_ns,
+            .receivedSvTimeUncertaintyInNs = entry.received_sv_time_uncertainty_in_ns,
+            .cN0DbHz = entry.c_n0_dbhz,
+            .pseudorangeRateMps = entry.pseudorange_rate_mps,
+            .pseudorangeRateUncertaintyMps = entry.pseudorange_rate_uncertainty_mps,
+            .accumulatedDeltaRangeState = entry.accumulated_delta_range_state,
+            .accumulatedDeltaRangeM = entry.accumulated_delta_range_m,
+            .accumulatedDeltaRangeUncertaintyM = entry.accumulated_delta_range_uncertainty_m,
+            .carrierFrequencyHz = entry.carrier_frequency_hz,
+            .carrierCycles = entry.carrier_cycles,
+            .carrierPhase = entry.carrier_phase,
+            .carrierPhaseUncertainty = entry.carrier_phase_uncertainty,
+            .multipathIndicator = static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                    entry.multipath_indicator),
+            .snrDb = entry.snr_db
+        };
+    }
+
+    auto clockVal = legacyGnssData->clock;
+    gnssData.clock = {
+        .gnssClockFlags = clockVal.flags,
+        .leapSecond = clockVal.leap_second,
+        .timeNs = clockVal.time_ns,
+        .timeUncertaintyNs = clockVal.time_uncertainty_ns,
+        .fullBiasNs = clockVal.full_bias_ns,
+        .biasNs = clockVal.bias_ns,
+        .biasUncertaintyNs = clockVal.bias_uncertainty_ns,
+        .driftNsps = clockVal.drift_nsps,
+        .driftUncertaintyNsps = clockVal.drift_uncertainty_nsps,
+        .hwClockDiscontinuityCount = clockVal.hw_clock_discontinuity_count
+    };
+
+    sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+}
+
+/*
+ * The code in the following method has been moved here from GnssLocationProvider.
+ * It converts GpsData to GnssData. This code is no longer required in
+ * GnssLocationProvider since GpsData is deprecated and no longer part of the
+ * GNSS interface.
+ */
+void GnssMeasurement::gpsMeasurementCb(GpsData* gpsData) {
+    if (sGnssMeasureCbIface == nullptr) {
+        ALOGE("%s: GNSSMeasurement Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (gpsData == nullptr) {
+        ALOGE("%s: Invalid GpsData from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssMeasurementCallback::GnssData gnssData;
+    gnssData.measurementCount = std::min(gpsData->measurement_count,
+                                         static_cast<size_t>(GnssMax::SVS_COUNT));
+
+
+    for (size_t i = 0; i < gnssData.measurementCount; i++) {
+        auto entry = gpsData->measurements[i];
+        gnssData.measurements[i].flags = entry.flags;
+        gnssData.measurements[i].svid = static_cast<int32_t>(entry.prn);
+        if (entry.prn >= 1 && entry.prn <= 32) {
+            gnssData.measurements[i].constellation = GnssConstellationType::GPS;
+        } else {
+            gnssData.measurements[i].constellation =
+                  GnssConstellationType::UNKNOWN;
+        }
+
+        gnssData.measurements[i].timeOffsetNs = entry.time_offset_ns;
+        gnssData.measurements[i].state = entry.state;
+        gnssData.measurements[i].receivedSvTimeInNs = entry.received_gps_tow_ns;
+        gnssData.measurements[i].receivedSvTimeUncertaintyInNs =
+            entry.received_gps_tow_uncertainty_ns;
+        gnssData.measurements[i].cN0DbHz = entry.c_n0_dbhz;
+        gnssData.measurements[i].pseudorangeRateMps = entry.pseudorange_rate_mps;
+        gnssData.measurements[i].pseudorangeRateUncertaintyMps =
+                entry.pseudorange_rate_uncertainty_mps;
+        gnssData.measurements[i].accumulatedDeltaRangeState =
+                entry.accumulated_delta_range_state;
+        gnssData.measurements[i].accumulatedDeltaRangeM =
+                entry.accumulated_delta_range_m;
+        gnssData.measurements[i].accumulatedDeltaRangeUncertaintyM =
+                entry.accumulated_delta_range_uncertainty_m;
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_FREQUENCY) {
+            gnssData.measurements[i].carrierFrequencyHz = entry.carrier_frequency_hz;
+        } else {
+            gnssData.measurements[i].carrierFrequencyHz = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE) {
+            gnssData.measurements[i].carrierPhase = entry.carrier_phase;
+        } else {
+            gnssData.measurements[i].carrierPhase = 0;
+        }
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_CARRIER_PHASE_UNCERTAINTY) {
+            gnssData.measurements[i].carrierPhaseUncertainty = entry.carrier_phase_uncertainty;
+        } else {
+            gnssData.measurements[i].carrierPhaseUncertainty = 0;
+        }
+
+        gnssData.measurements[i].multipathIndicator =
+                static_cast<IGnssMeasurementCallback::GnssMultipathIndicator>(
+                        entry.multipath_indicator);
+
+        if (entry.flags & GNSS_MEASUREMENT_HAS_SNR) {
+            gnssData.measurements[i].snrDb = entry.snr_db;
+        } else {
+            gnssData.measurements[i].snrDb = 0;
+        }
+    }
+
+    auto clockVal = gpsData->clock;
+    static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
+    auto flags = clockVal.flags;
+
+    gnssData.clock.leapSecond = clockVal.leap_second;
+    /*
+     * GnssClock only supports the more effective HW_CLOCK type, so type
+     * handling and documentation complexity has been removed.  To convert the
+     * old GPS_CLOCK types (active only in a limited number of older devices),
+     * the GPS time information is handled as an always discontinuous HW clock,
+     * with the GPS time information put into the full_bias_ns instead - so that
+     * time_ns - full_bias_ns = local estimate of GPS time. Additionally, the
+     * sign of full_bias_ns and bias_ns has flipped between GpsClock &
+     * GnssClock, so that is also handled below.
+     */
+    switch (clockVal.type) {
+        case GPS_CLOCK_TYPE_UNKNOWN:
+            // Clock type unsupported.
+            ALOGE("Unknown clock type provided.");
+            break;
+        case GPS_CLOCK_TYPE_LOCAL_HW_TIME:
+            // Already local hardware time. No need to do anything.
+            break;
+        case GPS_CLOCK_TYPE_GPS_TIME:
+            // GPS time, need to convert.
+            flags |= GPS_CLOCK_HAS_FULL_BIAS;
+            clockVal.full_bias_ns = clockVal.time_ns;
+            clockVal.time_ns = 0;
+            gnssData.clock.hwClockDiscontinuityCount =
+                    discontinuity_count_to_handle_old_clock_type++;
+            break;
+    }
+
+    gnssData.clock.timeNs = clockVal.time_ns;
+    gnssData.clock.timeUncertaintyNs = clockVal.time_uncertainty_ns;
+    /*
+     * Definition of sign for full_bias_ns & bias_ns has been changed since N,
+     * so flip signs here.
+     */
+    gnssData.clock.fullBiasNs = -(clockVal.full_bias_ns);
+    gnssData.clock.biasNs = -(clockVal.bias_ns);
+    gnssData.clock.biasUncertaintyNs = clockVal.bias_uncertainty_ns;
+    gnssData.clock.driftNsps = clockVal.drift_nsps;
+    gnssData.clock.driftUncertaintyNsps = clockVal.drift_uncertainty_nsps;
+    gnssData.clock.gnssClockFlags = clockVal.flags;
+
+    sGnssMeasureCbIface->GnssMeasurementCb(gnssData);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+Return<GnssMeasurement::GnssMeasurementStatus> GnssMeasurement::setCallback(
+        const sp<IGnssMeasurementCallback>& callback)  {
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+        return GnssMeasurementStatus::ERROR_GENERIC;
+    }
+    sGnssMeasureCbIface = callback;
+
+    return static_cast<GnssMeasurement::GnssMeasurementStatus>(
+            mGnssMeasureIface->init(&sGnssMeasurementCbs));
+}
+
+Return<void> GnssMeasurement::close()  {
+    if (mGnssMeasureIface == nullptr) {
+        ALOGE("%s: GnssMeasure interface is unavailable", __func__);
+    } else {
+        mGnssMeasureIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssMeasurement.h b/gnss/1.0/default/GnssMeasurement.h
new file mode 100644
index 0000000..9ff1435
--- /dev/null
+++ b/gnss/1.0/default/GnssMeasurement.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssMeasurement_H_
+#define android_hardware_gnss_V1_0_GnssMeasurement_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssMeasurement;
+using ::android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssData = ::GnssData;
+
+/*
+ * Extended interface for GNSS Measurements support. Also contains wrapper methods to allow methods
+ * from IGnssMeasurementCallback interface to be passed into the conventional implementation of the
+ * GNSS HAL.
+ */
+struct GnssMeasurement : public IGnssMeasurement {
+    GnssMeasurement(const GpsMeasurementInterface* gpsMeasurementIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssMeasurement follow.
+     * These declarations were generated from IGnssMeasurement.hal.
+     */
+    Return<GnssMeasurementStatus> setCallback(
+        const sp<IGnssMeasurementCallback>& callback) override;
+    Return<void> close() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssMeasurement base class.
+     */
+    static void gnssMeasurementCb(LegacyGnssData* data);
+     /*
+      * Deprecated callback added for backward compatibity for devices that do
+      * not support GnssData measurements.
+      */
+    static void gpsMeasurementCb(GpsData* data);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsMeasurementCallbacks sGnssMeasurementCbs;
+
+ private:
+    const GpsMeasurementInterface* mGnssMeasureIface = nullptr;
+    static sp<IGnssMeasurementCallback> sGnssMeasureCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssMeasurement_H_
diff --git a/gnss/1.0/default/GnssNavigationMessage.cpp b/gnss/1.0/default/GnssNavigationMessage.cpp
new file mode 100644
index 0000000..c98abf6
--- /dev/null
+++ b/gnss/1.0/default/GnssNavigationMessage.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNavigationMessageInterface"
+
+#include <log/log.h>
+
+#include "GnssNavigationMessage.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+sp<IGnssNavigationMessageCallback> GnssNavigationMessage::sGnssNavigationMsgCbIface = nullptr;
+
+GpsNavigationMessageCallbacks GnssNavigationMessage::sGnssNavigationMessageCb = {
+    .size = sizeof(GpsNavigationMessageCallbacks),
+    .navigation_message_callback = nullptr,
+    .gnss_navigation_message_callback = gnssNavigationMessageCb
+};
+
+GnssNavigationMessage::GnssNavigationMessage(
+        const GpsNavigationMessageInterface* gpsNavigationMessageIface) :
+    mGnssNavigationMessageIface(gpsNavigationMessageIface) {}
+
+void GnssNavigationMessage::gnssNavigationMessageCb(LegacyGnssNavigationMessage* message) {
+    if (sGnssNavigationMsgCbIface == nullptr) {
+        ALOGE("%s: GnssNavigation Message Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (message == nullptr) {
+        ALOGE("%s, received invalid GnssNavigationMessage from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNavigationMessageCallback::GnssNavigationMessage navigationMsg;
+
+    navigationMsg.svid = message->svid;
+    navigationMsg.type =
+            static_cast<IGnssNavigationMessageCallback::GnssNavigationMessageType>(message->type);
+    navigationMsg.status = message->status;
+    navigationMsg.messageId = message->message_id;
+    navigationMsg.submessageId = message->submessage_id;
+    navigationMsg.data.setToExternal(message->data, message->data_length);
+
+    sGnssNavigationMsgCbIface->gnssNavigationMessageCb(navigationMsg);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+Return<GnssNavigationMessage::GnssNavigationMessageStatus> GnssNavigationMessage::setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback)  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+        return GnssNavigationMessageStatus::ERROR_GENERIC;
+    }
+
+    sGnssNavigationMsgCbIface = callback;
+
+    return static_cast<GnssNavigationMessage::GnssNavigationMessageStatus>(
+            mGnssNavigationMessageIface->init(&sGnssNavigationMessageCb));
+}
+
+Return<void> GnssNavigationMessage::close()  {
+    if (mGnssNavigationMessageIface == nullptr) {
+        ALOGE("%s: GnssNavigationMessage not available", __func__);
+    } else {
+        mGnssNavigationMessageIface->close();
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssNavigationMessage.h b/gnss/1.0/default/GnssNavigationMessage.h
new file mode 100644
index 0000000..882854b
--- /dev/null
+++ b/gnss/1.0/default/GnssNavigationMessage.h
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+#define android_hardware_gnss_V1_0_GnssNavigationMessage_H_
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessage;
+using ::android::hardware::gnss::V1_0::IGnssNavigationMessageCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+using LegacyGnssNavigationMessage = ::GnssNavigationMessage;
+
+/*
+ * Extended interface for GNSS navigation message reporting support. Also contains wrapper methods
+ * to allow methods from IGnssNavigationMessageCallback interface to be passed into the conventional
+ * implementation of the GNSS HAL.
+ */
+struct GnssNavigationMessage : public IGnssNavigationMessage {
+    GnssNavigationMessage(const GpsNavigationMessageInterface* gpsNavigationMessageIface);
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNavigationMessage follow.
+     * These declarations were generated from IGnssNavigationMessage.hal.
+     */
+    Return<GnssNavigationMessageStatus> setCallback(
+        const sp<IGnssNavigationMessageCallback>& callback) override;
+    Return<void> close() override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssNavigationMessage base class.
+     */
+    static void gnssNavigationMessageCb(LegacyGnssNavigationMessage* message);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNavigationMessageCallbacks sGnssNavigationMessageCb;
+ private:
+    const GpsNavigationMessageInterface* mGnssNavigationMessageIface = nullptr;
+    static sp<IGnssNavigationMessageCallback> sGnssNavigationMsgCbIface;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNavigationMessage_H_
diff --git a/gnss/1.0/default/GnssNi.cpp b/gnss/1.0/default/GnssNi.cpp
new file mode 100644
index 0000000..ec57e8c
--- /dev/null
+++ b/gnss/1.0/default/GnssNi.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssNiInterface"
+
+#include "GnssNi.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssNi::sThreadFuncArgsList;
+sp<IGnssNiCallback> GnssNi::sGnssNiCbIface = nullptr;
+bool GnssNi::sInterfaceExists = false;
+
+GpsNiCallbacks GnssNi::sGnssNiCb = {
+    .notify_cb = niNotifyCb,
+    .create_thread_cb = createThreadCb
+};
+
+GnssNi::GnssNi(const GpsNiInterface* gpsNiIface) : mGnssNiIface(gpsNiIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+GnssNi::~GnssNi() {
+    sThreadFuncArgsList.clear();
+}
+
+pthread_t GnssNi::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+void GnssNi::niNotifyCb(GpsNiNotification* notification) {
+    if (sGnssNiCbIface == nullptr) {
+        ALOGE("%s: GNSS NI Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    if (notification == nullptr) {
+        ALOGE("%s: Invalid GpsNotification callback from GNSS HAL", __func__);
+        return;
+    }
+
+    IGnssNiCallback::GnssNiNotification notificationGnss = {
+        .notificationId =  notification->notification_id,
+        .niType = static_cast<IGnssNiCallback::GnssNiType>(notification->ni_type),
+        .notifyFlags = notification->notify_flags,
+        .timeoutSec = static_cast<uint32_t>(notification->timeout),
+        .defaultResponse =
+                static_cast<IGnssNiCallback::GnssUserResponseType>(notification->default_response),
+        .requestorId = notification->requestor_id,
+        .notificationMessage = notification->text,
+        .requestorIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->requestor_id_encoding),
+        .notificationIdEncoding =
+                static_cast<IGnssNiCallback::GnssNiEncodingType>(notification->text_encoding)
+    };
+
+    sGnssNiCbIface->niNotifyCb(notificationGnss);
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+Return<void> GnssNi::setCallback(const sp<IGnssNiCallback>& callback)  {
+    if (mGnssNiIface == nullptr) {
+       ALOGE("%s: GnssNi interface is unavailable", __func__);
+       return Void();
+    }
+
+    sGnssNiCbIface = callback;
+
+    mGnssNiIface->init(&sGnssNiCb);
+    return Void();
+}
+
+Return<void> GnssNi::respond(int32_t notifId, IGnssNiCallback::GnssUserResponseType userResponse)  {
+    if (mGnssNiIface == nullptr) {
+        ALOGE("%s: GnssNi interface is unavailable", __func__);
+    } else {
+        mGnssNiIface->respond(notifId, static_cast<GpsUserResponseType>(userResponse));
+    }
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssNi.h b/gnss/1.0/default/GnssNi.h
new file mode 100644
index 0000000..fe850b1
--- /dev/null
+++ b/gnss/1.0/default/GnssNi.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssNi_H_
+#define android_hardware_gnss_V1_0_GnssNi_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssNi.h>
+#include <hidl/Status.h>
+#include <hardware/gps.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssNi;
+using ::android::hardware::gnss::V1_0::IGnssNiCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * Extended interface for Network-initiated (NI) support. This interface is used to respond to
+ * NI notifications originating from the HAL. Also contains wrapper methods to allow methods from
+ * IGnssNiCallback interface to be passed into the conventional implementation of the GNSS HAL.
+ */
+struct GnssNi : public IGnssNi {
+    GnssNi(const GpsNiInterface* gpsNiIface);
+    ~GnssNi();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssNi follow.
+     * These declarations were generated from IGnssNi.hal.
+     */
+    Return<void> setCallback(const sp<IGnssNiCallback>& callback) override;
+    Return<void> respond(int32_t notifId,
+                         IGnssNiCallback::GnssUserResponseType userResponse) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default
+     * implementation. These methods are not part of the IGnssNi base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void niNotifyCb(GpsNiNotification* notification);
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsNiCallbacks sGnssNiCb;
+
+ private:
+    const GpsNiInterface* mGnssNiIface = nullptr;
+    static sp<IGnssNiCallback> sGnssNiCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssNi_H_
diff --git a/gnss/1.0/default/GnssUtils.cpp b/gnss/1.0/default/GnssUtils.cpp
new file mode 100644
index 0000000..82a516b
--- /dev/null
+++ b/gnss/1.0/default/GnssUtils.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include "GnssUtils.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using android::hardware::gnss::V1_0::GnssLocation;
+
+GnssLocation convertToGnssLocation(GpsLocation* location) {
+    GnssLocation gnssLocation = {};
+    if (location != nullptr) {
+        gnssLocation = {
+            // Bit operation AND with 1f below is needed to clear vertical accuracy,
+            // speed accuracy and bearing accuracy flags as some vendors are found
+            // to be setting these bits in pre-Android-O devices
+            .gnssLocationFlags = static_cast<uint16_t>(location->flags & 0x1f),
+            .latitudeDegrees = location->latitude,
+            .longitudeDegrees = location->longitude,
+            .altitudeMeters = location->altitude,
+            .speedMetersPerSec = location->speed,
+            .bearingDegrees = location->bearing,
+            .horizontalAccuracyMeters = location->accuracy,
+            // Older chipsets do not provide the following 3 fields, hence the flags
+            // HAS_VERTICAL_ACCURACY, HAS_SPEED_ACCURACY and HAS_BEARING_ACCURACY are
+            // not set and the field are set to zeros.
+            .verticalAccuracyMeters = 0,
+            .speedAccuracyMetersPerSecond = 0,
+            .bearingAccuracyDegrees = 0,
+            .timestamp = location->timestamp
+        };
+    }
+
+    return gnssLocation;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssUtils.h b/gnss/1.0/default/GnssUtils.h
new file mode 100644
index 0000000..fc2f547
--- /dev/null
+++ b/gnss/1.0/default/GnssUtils.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+#ifndef android_hardware_gnss_V1_0_GnssUtil_H_
+#define android_hardware_gnss_V1_0_GnssUtil_H_
+
+#include <hardware/gps.h>
+#include <android/hardware/gnss/1.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * This method converts a GpsLocation struct to a GnssLocation
+ * struct.
+ */
+GnssLocation convertToGnssLocation(GpsLocation* location);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif
diff --git a/gnss/1.0/default/GnssXtra.cpp b/gnss/1.0/default/GnssXtra.cpp
new file mode 100644
index 0000000..065bb33
--- /dev/null
+++ b/gnss/1.0/default/GnssXtra.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssHAL_GnssXtraInterface"
+
+#include "GnssXtra.h"
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+std::vector<std::unique_ptr<ThreadFuncArgs>> GnssXtra::sThreadFuncArgsList;
+sp<IGnssXtraCallback> GnssXtra::sGnssXtraCbIface = nullptr;
+bool GnssXtra::sInterfaceExists = false;
+
+GpsXtraCallbacks GnssXtra::sGnssXtraCb = {
+    .download_request_cb = gnssXtraDownloadRequestCb,
+    .create_thread_cb = createThreadCb,
+};
+
+GnssXtra::~GnssXtra() {
+    sThreadFuncArgsList.clear();
+}
+
+pthread_t GnssXtra::createThreadCb(const char* name, void (*start)(void*), void* arg) {
+    return createPthread(name, start, arg, &sThreadFuncArgsList);
+}
+
+GnssXtra::GnssXtra(const GpsXtraInterface* xtraIface) : mGnssXtraIface(xtraIface) {
+    /* Error out if an instance of the interface already exists. */
+    LOG_ALWAYS_FATAL_IF(sInterfaceExists);
+    sInterfaceExists = true;
+}
+
+void GnssXtra::gnssXtraDownloadRequestCb() {
+    if (sGnssXtraCbIface == nullptr) {
+        ALOGE("%s: GNSS Callback Interface configured incorrectly", __func__);
+        return;
+    }
+
+    sGnssXtraCbIface->downloadRequestCb();
+}
+
+// Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+Return<bool> GnssXtra::setCallback(const sp<IGnssXtraCallback>& callback)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    sGnssXtraCbIface = callback;
+
+    return (mGnssXtraIface->init(&sGnssXtraCb) == 0);
+}
+
+Return<bool> GnssXtra::injectXtraData(const hidl_string& xtraData)  {
+    if (mGnssXtraIface == nullptr) {
+        ALOGE("%s: Gnss Xtra interface is unavailable", __func__);
+        return false;
+    }
+
+    char* buf = new char[xtraData.size()];
+    const char* data = xtraData.c_str();
+
+    memcpy(buf, data, xtraData.size());
+
+    int ret = mGnssXtraIface->inject_xtra_data(buf, xtraData.size());
+    delete[] buf;
+    return (ret == 0);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
diff --git a/gnss/1.0/default/GnssXtra.h b/gnss/1.0/default/GnssXtra.h
new file mode 100644
index 0000000..7a0733a
--- /dev/null
+++ b/gnss/1.0/default/GnssXtra.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_gnss_V1_0_GnssXtra_H_
+#define android_hardware_gnss_V1_0_GnssXtra_H_
+
+#include <ThreadCreationWrapper.h>
+#include <android/hardware/gnss/1.0/IGnssXtra.h>
+#include <hardware/gps.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::gnss::V1_0::IGnssXtra;
+using ::android::hardware::gnss::V1_0::IGnssXtraCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+/*
+ * This interface is used by the GNSS HAL to request the framework to download XTRA data.
+ * Also contains wrapper methods to allow methods from IGnssXtraCallback interface to be passed
+ * into the conventional implementation of the GNSS HAL.
+ */
+struct GnssXtra : public IGnssXtra {
+    GnssXtra(const GpsXtraInterface* xtraIface);
+    ~GnssXtra();
+
+    /*
+     * Methods from ::android::hardware::gnss::V1_0::IGnssXtra follow.
+     * These declarations were generated from IGnssXtra.hal.
+     */
+    Return<bool> setCallback(const sp<IGnssXtraCallback>& callback) override;
+    Return<bool> injectXtraData(const hidl_string& xtraData) override;
+
+    /*
+     * Callback methods to be passed into the conventional GNSS HAL by the default implementation.
+     * These methods are not part of the IGnssXtra base class.
+     */
+    static pthread_t createThreadCb(const char* name, void (*start)(void*), void* arg);
+    static void gnssXtraDownloadRequestCb();
+
+    /*
+     * Holds function pointers to the callback methods.
+     */
+    static GpsXtraCallbacks sGnssXtraCb;
+
+ private:
+    const GpsXtraInterface* mGnssXtraIface = nullptr;
+    static sp<IGnssXtraCallback> sGnssXtraCbIface;
+    static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
+    static bool sInterfaceExists;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_gnss_V1_0_GnssXtra_H_
diff --git a/gnss/1.0/default/ThreadCreationWrapper.cpp b/gnss/1.0/default/ThreadCreationWrapper.cpp
new file mode 100644
index 0000000..2a5638f
--- /dev/null
+++ b/gnss/1.0/default/ThreadCreationWrapper.cpp
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+#include <ThreadCreationWrapper.h>
+
+void* threadFunc(void* arg) {
+    ThreadFuncArgs* threadArgs = reinterpret_cast<ThreadFuncArgs*>(arg);
+    threadArgs->fptr(threadArgs->args);
+    return nullptr;
+}
+
+pthread_t createPthread(const char* name,
+                        void (*start)(void*),
+                        void* arg, std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs) {
+    pthread_t threadId;
+    auto threadArgs = new ThreadFuncArgs(start, arg);
+    auto argPtr = std::unique_ptr<ThreadFuncArgs>(threadArgs);
+
+    listArgs->push_back(std::move(argPtr));
+
+    int ret = pthread_create(&threadId, nullptr, threadFunc, reinterpret_cast<void*>(
+            threadArgs));
+    if (ret != 0) {
+        ALOGE("pthread creation unsuccessful");
+    } else {
+        pthread_setname_np(threadId, name);
+    }
+    return threadId;
+}
diff --git a/gnss/1.0/default/ThreadCreationWrapper.h b/gnss/1.0/default/ThreadCreationWrapper.h
new file mode 100644
index 0000000..df0a9e4
--- /dev/null
+++ b/gnss/1.0/default/ThreadCreationWrapper.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+#define ANDROID_HARDWARE_GNSS_THREADCREATIONWRAPPER_H
+
+#include <pthread.h>
+#include <vector>
+#include <cutils/log.h>
+
+typedef void (*threadEntryFunc)(void* ret);
+
+/*
+ * This class facilitates createThreadCb methods in various GNSS interfaces to wrap
+ * pthread_create() from libc since its function signature differs from what is required by the
+ * conventional GNSS HAL. The arguments passed to pthread_create() need to be on heap and not on
+ * the stack of createThreadCb.
+ */
+struct ThreadFuncArgs {
+    ThreadFuncArgs(void (*start)(void*), void* arg) : fptr(start), args(arg) {}
+
+    /* pointer to the function of type void()(void*) that needs to be wrapped */
+    threadEntryFunc fptr;
+    /* argument for fptr to be called with */
+    void* args;
+};
+
+/*
+ * This method is simply a wrapper. It is required since pthread_create() requires an entry
+ * function pointer of type void*()(void*) and the GNSS hal requires as input a function pointer of
+ * type void()(void*).
+ */
+void* threadFunc(void* arg);
+
+/*
+ * This method is called by createThreadCb with a pointer to the vector that
+ * holds the pointers to the thread arguments. The arg and start parameters are
+ * first used to create a ThreadFuncArgs object which is then saved in the
+ * listArgs parameters. The created ThreadFuncArgs object is then used to invoke
+ * threadFunc() method which in-turn invokes pthread_create.
+ */
+pthread_t createPthread(const char* name, void (*start)(void*), void* arg,
+                        std::vector<std::unique_ptr<ThreadFuncArgs>> * listArgs);
+
+#endif
diff --git a/gnss/1.0/default/android.hardware.gnss@1.0-service.rc b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
new file mode 100644
index 0000000..eeb2e43
--- /dev/null
+++ b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
@@ -0,0 +1,4 @@
+service gnss_service /system/bin/hw/android.hardware.gnss@1.0-service
+    class main
+    user system
+    group system
diff --git a/gnss/1.0/default/service.cpp b/gnss/1.0/default/service.cpp
new file mode 100644
index 0000000..4e040c5
--- /dev/null
+++ b/gnss/1.0/default/service.cpp
@@ -0,0 +1,12 @@
+#define LOG_TAG "android.hardware.gnss@1.0-service"
+
+#include <android/hardware/gnss/1.0/IGnss.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::hardware::gnss::V1_0::IGnss;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IGnss>("gnss");
+}
diff --git a/gnss/1.0/types.hal b/gnss/1.0/types.hal
new file mode 100644
index 0000000..d5e0e9b
--- /dev/null
+++ b/gnss/1.0/types.hal
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package android.hardware.gnss@1.0;
+
+@export(name="", value_prefix="GNSS_MAX_")
+enum GnssMax : uint32_t {
+/** Maximum number of SVs for gnssSvStatusCb(). */
+    SVS_COUNT = 64,
+};
+
+/* Milliseconds since January 1, 1970 */
+typedef int64_t GnssUtcTime;
+
+/*
+ * Constellation type of GnssSvInfo
+ */
+
+@export(name="", value_prefix="GNSS_CONSTELLATION_")
+enum GnssConstellationType : uint8_t {
+    UNKNOWN = 0,
+    GPS     = 1,
+    SBAS    = 2,
+    GLONASS = 3,
+    QZSS    = 4,
+    BEIDOU  = 5,
+    GALILEO = 6,
+};
+
+/** Bit mask to indicate which values are valid in a GnssLocation object. */
+@export(name="", value_prefix="GPS_LOCATION_")
+enum GnssLocationFlags : uint16_t {
+    /** GnssLocation has valid latitude and longitude. */
+    HAS_LAT_LONG              = 0x0001,
+    /** GnssLocation has valid altitude. */
+    HAS_ALTITUDE              = 0x0002,
+    /** GnssLocation has valid speed. */
+    HAS_SPEED                 = 0x0004,
+    /** GnssLocation has valid bearing. */
+    HAS_BEARING               = 0x0008,
+    /** GpsLocation has valid horizontal accuracy. */
+    HAS_HORIZONTAL_ACCURACY   = 0x0010,
+    /** GpsLocation has valid vertical accuracy. */
+    HAS_VERTICAL_ACCURACY     = 0x0020,
+    /** GpsLocation has valid speed accuracy. */
+    HAS_SPEED_ACCURACY        = 0x0040,
+    /** GpsLocation has valid bearing accuracy. */
+    HAS_BEARING_ACCURACY      = 0x0080
+};
+
+/* Represents a location. */
+struct GnssLocation {
+    /* Contains GnssLocationFlags bits. */
+    bitfield<GnssLocationFlags> gnssLocationFlags;
+
+    /* Represents latitude in degrees. */
+    double latitudeDegrees;
+
+    /* Represents longitude in degrees. */
+    double longitudeDegrees;
+
+    /*
+     * Represents altitude in meters above the WGS 84 reference ellipsoid.
+     */
+    double altitudeMeters;
+
+    /* Represents speed in meters per second. */
+    float speedMetersPerSec;
+
+    /* Represents heading in degrees. */
+    float bearingDegrees;
+
+    /*
+    * Represents expected horizontal position accuracy, radial, in meters
+    * (68% confidence).
+    */
+    float horizontalAccuracyMeters;
+
+    /*
+    * Represents expected vertical position accuracy in meters
+    * (68% confidence).
+    */
+    float verticalAccuracyMeters;
+
+    /*
+    * Represents expected speed accuracy in meter per seconds
+    * (68% confidence).
+    */
+    float speedAccuracyMetersPerSecond;
+
+    /*
+    * Represents expected bearing accuracy in degrees
+    * (68% confidence).
+    */
+    float bearingAccuracyDegrees;
+
+    /* Timestamp for the location fix. */
+    GnssUtcTime timestamp;
+};
diff --git a/gnss/Android.bp b/gnss/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/gnss/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/graphics/Android.bp b/graphics/Android.bp
new file mode 100644
index 0000000..6d55dd1
--- /dev/null
+++ b/graphics/Android.bp
@@ -0,0 +1,12 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "allocator/2.0",
+    "allocator/2.0/default",
+    "allocator/2.0/vts/functional",
+    "common/1.0",
+    "composer/2.1",
+    "composer/2.1/default",
+    "mapper/2.0",
+    "mapper/2.0/default",
+    "mapper/2.0/vts/functional",
+]
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
new file mode 100644
index 0000000..48db3e9
--- /dev/null
+++ b/graphics/allocator/2.0/Android.bp
@@ -0,0 +1,222 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0",
+    srcs: [
+        "types.hal",
+        "IAllocator.hal",
+        "IAllocatorClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/types.cpp",
+        "android/hardware/graphics/allocator/2.0/AllocatorAll.cpp",
+        "android/hardware/graphics/allocator/2.0/AllocatorClientAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0",
+    srcs: [
+        "types.hal",
+        "IAllocator.hal",
+        "IAllocatorClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/types.h",
+        "android/hardware/graphics/allocator/2.0/IAllocator.h",
+        "android/hardware/graphics/allocator/2.0/IHwAllocator.h",
+        "android/hardware/graphics/allocator/2.0/BnHwAllocator.h",
+        "android/hardware/graphics/allocator/2.0/BpHwAllocator.h",
+        "android/hardware/graphics/allocator/2.0/BsAllocator.h",
+        "android/hardware/graphics/allocator/2.0/IAllocatorClient.h",
+        "android/hardware/graphics/allocator/2.0/IHwAllocatorClient.h",
+        "android/hardware/graphics/allocator/2.0/BnHwAllocatorClient.h",
+        "android/hardware/graphics/allocator/2.0/BpHwAllocatorClient.h",
+        "android/hardware/graphics/allocator/2.0/BsAllocatorClient.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.allocator@2.0",
+    generated_sources: ["android.hardware.graphics.allocator@2.0_genc++"],
+    generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator.vts.driver@2.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "types.hal",
+        "IAllocator.hal",
+        "IAllocatorClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/types.vts.cpp",
+        "android/hardware/graphics/allocator/2.0/Allocator.vts.cpp",
+        "android/hardware/graphics/allocator/2.0/AllocatorClient.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator.vts.driver@2.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "types.hal",
+        "IAllocator.hal",
+        "IAllocatorClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/types.vts.h",
+        "android/hardware/graphics/allocator/2.0/Allocator.vts.h",
+        "android/hardware/graphics/allocator/2.0/AllocatorClient.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.allocator.vts.driver@2.0",
+    generated_sources: ["android.hardware.graphics.allocator.vts.driver@2.0_genc++"],
+    generated_headers: ["android.hardware.graphics.allocator.vts.driver@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.allocator.vts.driver@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+        "android.hardware.graphics.allocator@2.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "IAllocator.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/Allocator.vts.cpp",
+        "android/hardware/graphics/allocator/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "IAllocator.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/Allocator.vts.h",
+        "android/hardware/graphics/allocator/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler",
+    generated_sources: ["android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.allocator@2.0-IAllocator-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+        "android.hardware.graphics.allocator@2.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "IAllocatorClient.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/AllocatorClient.vts.cpp",
+        "android/hardware/graphics/allocator/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.allocator@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/graphics/allocator/2.0/ $(genDir)/android/hardware/graphics/allocator/2.0/",
+    srcs: [
+        "IAllocatorClient.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/allocator/2.0/AllocatorClient.vts.h",
+        "android/hardware/graphics/allocator/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler",
+    generated_sources: ["android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.allocator@2.0-IAllocatorClient-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+        "android.hardware.graphics.allocator@2.0",
+    ],
+}
diff --git a/graphics/allocator/2.0/Android.mk b/graphics/allocator/2.0/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/graphics/allocator/2.0/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/graphics/allocator/2.0/IAllocator.hal b/graphics/allocator/2.0/IAllocator.hal
new file mode 100644
index 0000000..00d07d5
--- /dev/null
+++ b/graphics/allocator/2.0/IAllocator.hal
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.allocator@2.0;
+
+import IAllocatorClient;
+
+interface IAllocator {
+    enum Capability : int32_t {
+        /* reserved */
+        INVALID = 0,
+
+        /*
+         * IAllocatorClient::testAllocate must always return UNDEFINED unless
+         * this capability is supported.
+         */
+        TEST_ALLOCATE = 1,
+
+        /*
+         * IAllocatorClient::BufferDescriptorInfo::layerCount must be 1 unless
+         * this capability is supported.
+         */
+        LAYERED_BUFFERS = 2,
+    };
+
+    /*
+     * Provides a list of supported capabilities (as described in the
+     * definition of Capability above). This list must not change after
+     * initialization.
+     *
+     * @return capabilities is a list of supported capabilities.
+     */
+    @entry
+    @exit
+    @callflow(next="*")
+    getCapabilities() generates (vec<Capability> capabilities);
+
+    /*
+     * Retrieves implementation-defined debug information, which will be
+     * displayed during, for example, `dumpsys SurfaceFlinger`.
+     *
+     * @return debugInfo is a string of debug information.
+     */
+    @entry
+    @exit
+    @callflow(next="*")
+    dumpDebugInfo() generates (string debugInfo);
+
+    /*
+     * Creates a client of the allocator. All resources created by the client
+     * are owned by the client and are only visible to the client, unless they
+     * are exported by exportHandle.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *         NO_RESOURCES when no more client can currently be created.
+     * @return client is the newly created client.
+     */
+    @entry
+    @callflow(next="*")
+    createClient() generates (Error error, IAllocatorClient client);
+};
diff --git a/graphics/allocator/2.0/IAllocatorClient.hal b/graphics/allocator/2.0/IAllocatorClient.hal
new file mode 100644
index 0000000..080e3ea
--- /dev/null
+++ b/graphics/allocator/2.0/IAllocatorClient.hal
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.allocator@2.0;
+
+import android.hardware.graphics.common@1.0::PixelFormat;
+
+interface IAllocatorClient {
+    struct BufferDescriptorInfo {
+        /*
+         * The width specifies how many columns of pixels must be in the
+         * allocated buffer, but does not necessarily represent the offset in
+         * columns between the same column in adjacent rows. The rows may be
+         * padded.
+         */
+        uint32_t width;
+
+       /*
+        * The height specifies how many rows of pixels must be in the
+        * allocated buffer.
+        */
+        uint32_t height;
+
+       /*
+        * The number of image layers that must be in the allocated buffer.
+        */
+        uint32_t layerCount;
+
+        /* Buffer pixel format. */
+        PixelFormat format;
+
+        /*
+         * Buffer producer usage mask; valid flags can be found in the
+         * definition of ProducerUsage.
+         */
+        uint64_t producerUsageMask;
+
+        /*
+         * Buffer consumer usage mask; valid flags can be found in the
+         * definition of ConsumerUsage.
+         */
+        uint64_t consumerUsageMask;
+    };
+
+    /*
+     * Creates a new, opaque buffer descriptor.
+     *
+     * @param descriptorInfo specifies the attributes of the buffer
+     *        descriptor.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_VALUE when any attribute in descriptorInfo is invalid.
+     *         NO_RESOURCES when no more descriptors can currently be created.
+     * @return descriptor is the newly created buffer descriptor.
+     */
+    @entry
+    @callflow(next="*")
+    createDescriptor(BufferDescriptorInfo descriptorInfo)
+          generates (Error error,
+                     BufferDescriptor descriptor);
+
+    /*
+     * Destroys an existing buffer descriptor.
+     *
+     * @param descriptor is the descriptor to destroy.
+     * @return error is either NONE or BAD_DESCRIPTOR.
+     */
+    @exit
+    @callflow(next="*")
+    destroyDescriptor(BufferDescriptor descriptor) generates (Error error);
+
+    /*
+     * Tests whether a buffer allocation can succeed, ignoring potential
+     * resource contention which might lead to a NO_RESOURCES error.
+     *
+     * @param descriptors is a list of buffer descriptors.
+     * @return error is NONE or NOT_SHARED upon success;
+     *         NONE when buffers can be created and share a backing store.
+     *         NOT_SHARED when buffers can be created but require more than a
+     *                    backing store.
+     *         Otherwise,
+     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
+     *         UNSUPPORTED when any of the descriptors can never be satisfied.
+     *         UNDEFINED when TEST_ALLOCATE is not listed in getCapabilities.
+     */
+    @callflow(next="allocate")
+    testAllocate(vec<BufferDescriptor> descriptors) generates (Error error);
+
+    /*
+     * Attempts to allocate a list of buffers sharing a backing store.
+     *
+     * Each buffer must correspond to one of the descriptors passed into the
+     * function and must hold a reference to its backing store. If the device
+     * is unable to share the backing store between the buffers, it must
+     * attempt to allocate the buffers with different backing stores and
+     * return NOT_SHARED if it is successful.
+     *
+     * @param descriptors is the buffer descriptors to attempt to allocate.
+     * @return error is NONE or NOT_SHARED upon success;
+     *         NONE when buffers can be created and share a backing store.
+     *         NOT_SHARED when buffers can be created but require more than a
+     *                    backing store.
+     *         Otherwise,
+     *         BAD_DESCRIPTOR when any of the descriptors is invalid.
+     *         UNSUPPORTED when any of the descriptors can never be satisfied.
+     *         NO_RESOURCES when any of the buffers cannot be created at this
+     *                      time.
+     * @return buffers is the allocated buffers.
+     */
+    @callflow(next="exportHandle")
+    allocate(vec<BufferDescriptor> descriptors)
+        generates (Error error,
+                   vec<Buffer> buffers);
+
+    /*
+     * Frees a buffer.
+     *
+     * @param buffer is the buffer to be freed.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_BUFFER when the buffer is invalid.
+     */
+    @exit
+    @callflow(next="*")
+    free(Buffer buffer) generates (Error error);
+
+    /*
+     * Exports a buffer for use in other client libraries or for cross-process
+     * sharing.
+     *
+     * The exported handle is a handle to the backing store of the buffer, not
+     * to the buffer itself. It however may not hold any reference to the
+     * backing store and may be considered invalid by client libraries. To use
+     * it and, in most cases, to save it for later use, a client must make a
+     * clone of the handle and have the cloned handle hold a reference to the
+     * backing store. Such a cloned handle will stay valid even after the
+     * original buffer is freed. Refer to native_handle_clone and IMapper for
+     * how a handle is cloned and how a reference is added.
+     *
+     * @param descriptor is the descriptor used to allocate the buffer.
+     * @param buffer is the buffer to be exported.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DESCRIPTOR when the descriptor is invalid.
+     *         BAD_BUFFER when the buffer is invalid.
+     *         BAD_VALUE when descriptor and buffer do not match.
+     *         NO_RESOURCES when the buffer cannot be exported at this time.
+     * @return bufferHandle is the exported handle.
+     */
+    @callflow(next="free")
+    exportHandle(BufferDescriptor descriptor,
+                 Buffer buffer)
+      generates (Error error,
+                 handle bufferHandle);
+};
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
new file mode 100644
index 0000000..f0c736c
--- /dev/null
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -0,0 +1,41 @@
+cc_library_shared {
+    name: "android.hardware.graphics.allocator@2.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Gralloc.cpp"],
+    cppflags: ["-Wall", "-Wextra"],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.allocator@2.0-service",
+    relative_install_path: "hw",
+    srcs: ["service.cpp"],
+    init_rc: ["android.hardware.graphics.allocator@2.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+}
+
+cc_library_static {
+    name: "libgralloc1-adapter",
+    srcs: ["gralloc1-adapter.cpp", "Gralloc1On0Adapter.cpp"],
+    include_dirs: ["system/core/libsync/include"],
+    cflags: ["-Wall", "-Wextra", "-Wno-unused-parameter"],
+    export_include_dirs: ["."],
+}
diff --git a/graphics/allocator/2.0/default/Gralloc.cpp b/graphics/allocator/2.0/default/Gralloc.cpp
new file mode 100644
index 0000000..3a102d1
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc.cpp
@@ -0,0 +1,471 @@
+/*
+ * 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 "GrallocPassthrough"
+
+#include <mutex>
+#include <type_traits>
+#include <unordered_set>
+#include <vector>
+
+#include <string.h>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+#include "Gralloc.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+class GrallocHal : public IAllocator {
+public:
+    GrallocHal(const hw_module_t* module);
+    virtual ~GrallocHal();
+
+    // IAllocator interface
+    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
+    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+    Return<void> createClient(createClient_cb hidl_cb) override;
+
+    Error createDescriptor(
+            const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
+            BufferDescriptor* outDescriptor);
+    Error destroyDescriptor(BufferDescriptor descriptor);
+
+    Error testAllocate(const hidl_vec<BufferDescriptor>& descriptors);
+    Error allocate(const hidl_vec<BufferDescriptor>& descriptors,
+            hidl_vec<Buffer>* outBuffers);
+    Error free(Buffer buffer);
+
+    Error exportHandle(Buffer buffer, const native_handle_t** outHandle);
+
+private:
+    void initCapabilities();
+
+    template<typename T>
+    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    bool hasCapability(Capability capability) const;
+
+    gralloc1_device_t* mDevice;
+
+    std::unordered_set<Capability> mCapabilities;
+
+    struct {
+        GRALLOC1_PFN_DUMP dump;
+        GRALLOC1_PFN_CREATE_DESCRIPTOR createDescriptor;
+        GRALLOC1_PFN_DESTROY_DESCRIPTOR destroyDescriptor;
+        GRALLOC1_PFN_SET_DIMENSIONS setDimensions;
+        GRALLOC1_PFN_SET_FORMAT setFormat;
+        GRALLOC1_PFN_SET_LAYER_COUNT setLayerCount;
+        GRALLOC1_PFN_SET_CONSUMER_USAGE setConsumerUsage;
+        GRALLOC1_PFN_SET_PRODUCER_USAGE setProducerUsage;
+        GRALLOC1_PFN_ALLOCATE allocate;
+        GRALLOC1_PFN_RELEASE release;
+    } mDispatch;
+};
+
+class GrallocClient : public IAllocatorClient {
+public:
+    GrallocClient(GrallocHal& hal);
+    virtual ~GrallocClient();
+
+    // IAllocatorClient interface
+    Return<void> createDescriptor(const BufferDescriptorInfo& descriptorInfo,
+            createDescriptor_cb hidl_cb) override;
+    Return<Error> destroyDescriptor(BufferDescriptor descriptor) override;
+
+    Return<Error> testAllocate(
+            const hidl_vec<BufferDescriptor>& descriptors) override;
+    Return<void> allocate(const hidl_vec<BufferDescriptor>& descriptors,
+            allocate_cb hidl_cb) override;
+    Return<Error> free(Buffer buffer) override;
+
+    Return<void> exportHandle(BufferDescriptor descriptor,
+            Buffer buffer, exportHandle_cb hidl_cb) override;
+
+private:
+    GrallocHal& mHal;
+
+    std::mutex mMutex;
+    std::unordered_set<BufferDescriptor> mDescriptors;
+    std::unordered_set<Buffer> mBuffers;
+};
+
+GrallocHal::GrallocHal(const hw_module_t* module)
+    : mDevice(nullptr), mDispatch()
+{
+    int status = gralloc1_open(module, &mDevice);
+    if (status) {
+        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+                strerror(-status));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+GrallocHal::~GrallocHal()
+{
+    gralloc1_close(mDevice);
+}
+
+void GrallocHal::initCapabilities()
+{
+    uint32_t count;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<Capability> caps(count);
+    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
+              std::underlying_type<Capability>::type*>(caps.data()));
+    caps.resize(count);
+
+    mCapabilities.insert(caps.cbegin(), caps.cend());
+}
+
+template<typename T>
+void GrallocHal::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 GrallocHal::initDispatch()
+{
+    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);
+    if (hasCapability(Capability::LAYERED_BUFFERS)) {
+        initDispatch(GRALLOC1_FUNCTION_SET_LAYER_COUNT,
+                &mDispatch.setLayerCount);
+    }
+    initDispatch(GRALLOC1_FUNCTION_SET_CONSUMER_USAGE,
+            &mDispatch.setConsumerUsage);
+    initDispatch(GRALLOC1_FUNCTION_SET_PRODUCER_USAGE,
+            &mDispatch.setProducerUsage);
+    initDispatch(GRALLOC1_FUNCTION_ALLOCATE, &mDispatch.allocate);
+    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+}
+
+bool GrallocHal::hasCapability(Capability capability) const
+{
+    return (mCapabilities.count(capability) > 0);
+}
+
+Return<void> GrallocHal::getCapabilities(getCapabilities_cb hidl_cb)
+{
+    std::vector<Capability> caps(
+            mCapabilities.cbegin(), mCapabilities.cend());
+
+    hidl_vec<Capability> reply;
+    reply.setToExternal(caps.data(), caps.size());
+    hidl_cb(reply);
+
+    return Void();
+}
+
+Return<void> GrallocHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
+{
+    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';
+
+    hidl_string reply;
+    reply.setToExternal(buf.data(), len);
+    hidl_cb(reply);
+
+    return Void();
+}
+
+Return<void> GrallocHal::createClient(createClient_cb hidl_cb)
+{
+    sp<IAllocatorClient> client = new GrallocClient(*this);
+    hidl_cb(Error::NONE, client);
+
+    return Void();
+}
+
+Error GrallocHal::createDescriptor(
+        const IAllocatorClient::BufferDescriptorInfo& descriptorInfo,
+        BufferDescriptor* outDescriptor)
+{
+    gralloc1_buffer_descriptor_t descriptor;
+    int32_t err = mDispatch.createDescriptor(mDevice, &descriptor);
+    if (err != GRALLOC1_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    err = mDispatch.setDimensions(mDevice, descriptor,
+            descriptorInfo.width, descriptorInfo.height);
+    if (err == GRALLOC1_ERROR_NONE) {
+        err = mDispatch.setFormat(mDevice, descriptor,
+                static_cast<int32_t>(descriptorInfo.format));
+    }
+    if (err == GRALLOC1_ERROR_NONE) {
+        if (hasCapability(Capability::LAYERED_BUFFERS)) {
+            err = mDispatch.setLayerCount(mDevice, descriptor,
+                    descriptorInfo.layerCount);
+        } else if (descriptorInfo.layerCount != 1) {
+            err = GRALLOC1_ERROR_BAD_VALUE;
+        }
+    }
+    if (err == GRALLOC1_ERROR_NONE) {
+        uint64_t producerUsageMask = descriptorInfo.producerUsageMask;
+        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_READ_OFTEN) {
+            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_READ;
+        }
+        if (producerUsageMask & GRALLOC1_PRODUCER_USAGE_CPU_WRITE_OFTEN) {
+            producerUsageMask |= GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+        }
+        err = mDispatch.setProducerUsage(mDevice, descriptor,
+                descriptorInfo.producerUsageMask);
+    }
+    if (err == GRALLOC1_ERROR_NONE) {
+        uint64_t consumerUsageMask = descriptorInfo.consumerUsageMask;
+        if (consumerUsageMask & GRALLOC1_CONSUMER_USAGE_CPU_READ_OFTEN) {
+            consumerUsageMask |= GRALLOC1_CONSUMER_USAGE_CPU_READ;
+        }
+        err = mDispatch.setConsumerUsage(mDevice, descriptor,
+                consumerUsageMask);
+    }
+
+    if (err == GRALLOC1_ERROR_NONE) {
+        *outDescriptor = descriptor;
+    } else {
+        mDispatch.destroyDescriptor(mDevice, descriptor);
+    }
+
+    return static_cast<Error>(err);
+}
+
+Error GrallocHal::destroyDescriptor(BufferDescriptor descriptor)
+{
+    int32_t err = mDispatch.destroyDescriptor(mDevice, descriptor);
+    return static_cast<Error>(err);
+}
+
+Error GrallocHal::testAllocate(const hidl_vec<BufferDescriptor>& descriptors)
+{
+    if (!hasCapability(Capability::TEST_ALLOCATE)) {
+        return Error::UNDEFINED;
+    }
+
+    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
+            descriptors.data(), nullptr);
+    return static_cast<Error>(err);
+}
+
+Error GrallocHal::allocate(const hidl_vec<BufferDescriptor>& descriptors,
+        hidl_vec<Buffer>* outBuffers)
+{
+    std::vector<buffer_handle_t> buffers(descriptors.size());
+    int32_t err = mDispatch.allocate(mDevice, descriptors.size(),
+            descriptors.data(), buffers.data());
+    if (err == GRALLOC1_ERROR_NONE || err == GRALLOC1_ERROR_NOT_SHARED) {
+        outBuffers->resize(buffers.size());
+        for (size_t i = 0; i < outBuffers->size(); i++) {
+            (*outBuffers)[i] = static_cast<Buffer>(
+                    reinterpret_cast<uintptr_t>(buffers[i]));
+        }
+    }
+
+    return static_cast<Error>(err);
+}
+
+Error GrallocHal::free(Buffer buffer)
+{
+    buffer_handle_t handle = reinterpret_cast<buffer_handle_t>(
+            static_cast<uintptr_t>(buffer));
+
+    int32_t err = mDispatch.release(mDevice, handle);
+    return static_cast<Error>(err);
+}
+
+Error GrallocHal::exportHandle(Buffer buffer,
+        const native_handle_t** outHandle)
+{
+    // we rely on the caller to validate buffer here
+    *outHandle = reinterpret_cast<buffer_handle_t>(
+            static_cast<uintptr_t>(buffer));
+    return Error::NONE;
+}
+
+GrallocClient::GrallocClient(GrallocHal& hal)
+    : mHal(hal)
+{
+}
+
+GrallocClient::~GrallocClient()
+{
+    if (!mBuffers.empty()) {
+        ALOGW("client destroyed with valid buffers");
+        for (auto buf : mBuffers) {
+            mHal.free(buf);
+        }
+    }
+
+    if (!mDescriptors.empty()) {
+        ALOGW("client destroyed with valid buffer descriptors");
+        for (auto desc : mDescriptors) {
+            mHal.destroyDescriptor(desc);
+        }
+    }
+}
+
+Return<void> GrallocClient::createDescriptor(
+        const BufferDescriptorInfo& descriptorInfo,
+        createDescriptor_cb hidl_cb)
+{
+    BufferDescriptor descriptor = 0;
+    Error err = mHal.createDescriptor(descriptorInfo, &descriptor);
+
+    if (err == Error::NONE) {
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        auto result = mDescriptors.insert(descriptor);
+        if (!result.second) {
+            ALOGW("duplicated buffer descriptor id returned");
+            mHal.destroyDescriptor(descriptor);
+            err = Error::NO_RESOURCES;
+        }
+    }
+
+    hidl_cb(err, descriptor);
+    return Void();
+}
+
+Return<Error> GrallocClient::destroyDescriptor(BufferDescriptor descriptor)
+{
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (!mDescriptors.erase(descriptor)) {
+            return Error::BAD_DESCRIPTOR;
+        }
+    }
+
+    return mHal.destroyDescriptor(descriptor);
+}
+
+Return<Error> GrallocClient::testAllocate(
+        const hidl_vec<BufferDescriptor>& descriptors)
+{
+    return mHal.testAllocate(descriptors);
+}
+
+Return<void> GrallocClient::allocate(
+        const hidl_vec<BufferDescriptor>& descriptors,
+        allocate_cb hidl_cb) {
+    hidl_vec<Buffer> buffers;
+    Error err = mHal.allocate(descriptors, &buffers);
+
+    if (err == Error::NONE || err == Error::NOT_SHARED) {
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        for (size_t i = 0; i < buffers.size(); i++) {
+            auto result = mBuffers.insert(buffers[i]);
+            if (!result.second) {
+                ALOGW("duplicated buffer id returned");
+
+                for (size_t j = 0; j < buffers.size(); j++) {
+                    if (j < i) {
+                        mBuffers.erase(buffers[i]);
+                    }
+                    mHal.free(buffers[i]);
+                }
+
+                buffers = hidl_vec<Buffer>();
+                err = Error::NO_RESOURCES;
+                break;
+            }
+        }
+    }
+
+    hidl_cb(err, buffers);
+    return Void();
+}
+
+Return<Error> GrallocClient::free(Buffer buffer)
+{
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (!mBuffers.erase(buffer)) {
+            return Error::BAD_BUFFER;
+        }
+    }
+
+    return mHal.free(buffer);
+}
+
+Return<void> GrallocClient::exportHandle(BufferDescriptor /*descriptor*/,
+        Buffer buffer, exportHandle_cb hidl_cb)
+{
+    const native_handle_t* handle = nullptr;
+
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        if (mBuffers.count(buffer) == 0) {
+            hidl_cb(Error::BAD_BUFFER, handle);
+            return Void();
+        }
+    }
+
+    Error err = mHal.exportHandle(buffer, &handle);
+
+    hidl_cb(err, handle);
+    return Void();
+}
+
+IAllocator* HIDL_FETCH_IAllocator(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;
+    if (major != 1) {
+        ALOGE("unknown gralloc module major version %d", major);
+        return nullptr;
+    }
+
+    return new GrallocHal(module);
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc.h b/graphics/allocator/2.0/default/Gralloc.h
new file mode 100644
index 0000000..c79eeaa
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc.h
@@ -0,0 +1,38 @@
+/*
+ * 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_ALLOCATOR_V2_0_GRALLOC_H
+#define ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace implementation {
+
+extern "C" IAllocator* HIDL_FETCH_IAllocator(const char* name);
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace allocator
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_ALLOCATOR_V2_0_GRALLOC_H
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
new file mode 100644
index 0000000..4b9c9e1
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1On0Adapter.cpp
@@ -0,0 +1,560 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "Gralloc1On0Adapter"
+//#define LOG_NDEBUG 0
+
+#include "Gralloc1On0Adapter.h"
+#include "gralloc1-adapter.h"
+
+#include <hardware/gralloc.h>
+
+#include <utils/Log.h>
+#include <sync/sync.h>
+
+#include <inttypes.h>
+
+template <typename PFN, typename T>
+static gralloc1_function_pointer_t asFP(T function)
+{
+    static_assert(std::is_same<PFN, T>::value, "Incompatible function pointer");
+    return reinterpret_cast<gralloc1_function_pointer_t>(function);
+}
+
+namespace android {
+namespace hardware {
+
+Gralloc1On0Adapter::Gralloc1On0Adapter(const hw_module_t* module)
+  : gralloc1_device_t(),
+    mModule(reinterpret_cast<const gralloc_module_t*>(module)),
+    mDevice(nullptr)
+{
+    ALOGV("Constructing");
+
+    int minor = 0;
+    mModule->perform(mModule,
+            GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR,
+            &minor);
+    mMinorVersion = minor;
+
+    common.tag = HARDWARE_DEVICE_TAG,
+    common.version = HARDWARE_DEVICE_API_VERSION(0, 0),
+    common.module = const_cast<struct hw_module_t*>(module),
+    common.close = closeHook,
+
+    getCapabilities = getCapabilitiesHook;
+    getFunction = getFunctionHook;
+    int error = ::gralloc_open(&(mModule->common), &mDevice);
+    if (error) {
+        ALOGE("Failed to open gralloc0 module: %d", error);
+    }
+    ALOGV("Opened gralloc0 device %p", mDevice);
+}
+
+Gralloc1On0Adapter::~Gralloc1On0Adapter()
+{
+    ALOGV("Destructing");
+    if (mDevice) {
+        ALOGV("Closing gralloc0 device %p", mDevice);
+        ::gralloc_close(mDevice);
+    }
+}
+
+void Gralloc1On0Adapter::doGetCapabilities(uint32_t* outCount,
+        int32_t* outCapabilities)
+{
+    *outCount = 0;
+}
+
+gralloc1_function_pointer_t Gralloc1On0Adapter::doGetFunction(
+        int32_t intDescriptor)
+{
+    constexpr auto lastDescriptor =
+            static_cast<int32_t>(GRALLOC1_LAST_FUNCTION);
+    if (intDescriptor < 0 || intDescriptor > lastDescriptor) {
+        ALOGE("Invalid function descriptor");
+        return nullptr;
+    }
+
+    auto descriptor =
+            static_cast<gralloc1_function_descriptor_t>(intDescriptor);
+    switch (descriptor) {
+        case GRALLOC1_FUNCTION_DUMP:
+            return asFP<GRALLOC1_PFN_DUMP>(dumpHook);
+        case GRALLOC1_FUNCTION_CREATE_DESCRIPTOR:
+            return asFP<GRALLOC1_PFN_CREATE_DESCRIPTOR>(createDescriptorHook);
+        case GRALLOC1_FUNCTION_DESTROY_DESCRIPTOR:
+            return asFP<GRALLOC1_PFN_DESTROY_DESCRIPTOR>(destroyDescriptorHook);
+        case GRALLOC1_FUNCTION_SET_CONSUMER_USAGE:
+            return asFP<GRALLOC1_PFN_SET_CONSUMER_USAGE>(setConsumerUsageHook);
+        case GRALLOC1_FUNCTION_SET_DIMENSIONS:
+            return asFP<GRALLOC1_PFN_SET_DIMENSIONS>(setDimensionsHook);
+        case GRALLOC1_FUNCTION_SET_FORMAT:
+            return asFP<GRALLOC1_PFN_SET_FORMAT>(setFormatHook);
+        case GRALLOC1_FUNCTION_SET_LAYER_COUNT:
+            return asFP<GRALLOC1_PFN_SET_LAYER_COUNT>(setLayerCountHook);
+        case GRALLOC1_FUNCTION_SET_PRODUCER_USAGE:
+            return asFP<GRALLOC1_PFN_SET_PRODUCER_USAGE>(setProducerUsageHook);
+        case GRALLOC1_FUNCTION_GET_BACKING_STORE:
+            return asFP<GRALLOC1_PFN_GET_BACKING_STORE>(
+                    bufferHook<decltype(&Buffer::getBackingStore),
+                    &Buffer::getBackingStore, gralloc1_backing_store_t*>);
+        case GRALLOC1_FUNCTION_GET_CONSUMER_USAGE:
+            return asFP<GRALLOC1_PFN_GET_CONSUMER_USAGE>(getConsumerUsageHook);
+        case GRALLOC1_FUNCTION_GET_DIMENSIONS:
+            return asFP<GRALLOC1_PFN_GET_DIMENSIONS>(
+                    bufferHook<decltype(&Buffer::getDimensions),
+                    &Buffer::getDimensions, uint32_t*, uint32_t*>);
+        case GRALLOC1_FUNCTION_GET_FORMAT:
+            return asFP<GRALLOC1_PFN_GET_FORMAT>(
+                    bufferHook<decltype(&Buffer::getFormat),
+                    &Buffer::getFormat, int32_t*>);
+        case GRALLOC1_FUNCTION_GET_LAYER_COUNT:
+            return asFP<GRALLOC1_PFN_GET_LAYER_COUNT>(
+                    bufferHook<decltype(&Buffer::getLayerCount),
+                    &Buffer::getLayerCount, uint32_t*>);
+        case GRALLOC1_FUNCTION_GET_PRODUCER_USAGE:
+            return asFP<GRALLOC1_PFN_GET_PRODUCER_USAGE>(getProducerUsageHook);
+        case GRALLOC1_FUNCTION_GET_STRIDE:
+            return asFP<GRALLOC1_PFN_GET_STRIDE>(
+                    bufferHook<decltype(&Buffer::getStride),
+                    &Buffer::getStride, uint32_t*>);
+        case GRALLOC1_FUNCTION_ALLOCATE:
+            if (mDevice != nullptr) {
+                return asFP<GRALLOC1_PFN_ALLOCATE>(allocateHook);
+            } else {
+                return nullptr;
+            }
+        case GRALLOC1_FUNCTION_RETAIN:
+            return asFP<GRALLOC1_PFN_RETAIN>(retainHook);
+        case GRALLOC1_FUNCTION_RELEASE:
+            return asFP<GRALLOC1_PFN_RELEASE>(releaseHook);
+        case GRALLOC1_FUNCTION_GET_NUM_FLEX_PLANES:
+            return asFP<GRALLOC1_PFN_GET_NUM_FLEX_PLANES>(
+                    bufferHook<decltype(&Buffer::getNumFlexPlanes),
+                    &Buffer::getNumFlexPlanes, uint32_t*>);
+        case GRALLOC1_FUNCTION_LOCK:
+            return asFP<GRALLOC1_PFN_LOCK>(
+                    lockHook<void*, &Gralloc1On0Adapter::lock>);
+        case GRALLOC1_FUNCTION_LOCK_FLEX:
+            return asFP<GRALLOC1_PFN_LOCK_FLEX>(
+                    lockHook<struct android_flex_layout,
+                    &Gralloc1On0Adapter::lockFlex>);
+        case GRALLOC1_FUNCTION_UNLOCK:
+            return asFP<GRALLOC1_PFN_UNLOCK>(unlockHook);
+        case GRALLOC1_FUNCTION_INVALID:
+            ALOGE("Invalid function descriptor");
+            return nullptr;
+    }
+
+    ALOGE("Unknown function descriptor: %d", intDescriptor);
+    return nullptr;
+}
+
+void Gralloc1On0Adapter::dump(uint32_t* outSize, char* outBuffer)
+{
+    ALOGV("dump(%u (%p), %p", outSize ? *outSize : 0, outSize, outBuffer);
+
+    if (!mDevice->dump) {
+        // dump is optional on gralloc0 implementations
+        *outSize = 0;
+        return;
+    }
+
+    if (!outBuffer) {
+        constexpr int32_t BUFFER_LENGTH = 4096;
+        char buffer[BUFFER_LENGTH] = {};
+        mDevice->dump(mDevice, buffer, BUFFER_LENGTH);
+        buffer[BUFFER_LENGTH - 1] = 0; // Ensure the buffer is null-terminated
+        size_t actualLength = std::strlen(buffer);
+        mCachedDump.resize(actualLength);
+        std::copy_n(buffer, actualLength, mCachedDump.begin());
+        *outSize = static_cast<uint32_t>(actualLength);
+    } else {
+        *outSize = std::min(*outSize,
+                static_cast<uint32_t>(mCachedDump.size()));
+        outBuffer = std::copy_n(mCachedDump.cbegin(), *outSize, outBuffer);
+    }
+}
+
+gralloc1_error_t Gralloc1On0Adapter::createDescriptor(
+        gralloc1_buffer_descriptor_t* outDescriptor)
+{
+    auto descriptorId = sNextBufferDescriptorId++;
+    std::lock_guard<std::mutex> lock(mDescriptorMutex);
+    mDescriptors.emplace(descriptorId, std::make_shared<Descriptor>());
+
+    ALOGV("Created descriptor %" PRIu64, descriptorId);
+
+    *outDescriptor = descriptorId;
+    return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::destroyDescriptor(
+        gralloc1_buffer_descriptor_t descriptor)
+{
+    ALOGV("Destroying descriptor %" PRIu64, descriptor);
+
+    std::lock_guard<std::mutex> lock(mDescriptorMutex);
+    if (mDescriptors.count(descriptor) == 0) {
+        return GRALLOC1_ERROR_BAD_DESCRIPTOR;
+    }
+
+    mDescriptors.erase(descriptor);
+    return GRALLOC1_ERROR_NONE;
+}
+
+Gralloc1On0Adapter::Buffer::Buffer(buffer_handle_t handle,
+        gralloc1_backing_store_t store, const Descriptor& descriptor,
+        uint32_t stride, uint32_t numFlexPlanes, bool wasAllocated)
+  : mHandle(handle),
+    mReferenceCount(1),
+    mStore(store),
+    mDescriptor(descriptor),
+    mStride(stride),
+    mNumFlexPlanes(numFlexPlanes),
+    mWasAllocated(wasAllocated) {}
+
+gralloc1_error_t Gralloc1On0Adapter::allocate(
+        gralloc1_buffer_descriptor_t id,
+        const std::shared_ptr<Descriptor>& descriptor,
+        buffer_handle_t* outBufferHandle)
+{
+    ALOGV("allocate(%" PRIu64 ")", id);
+
+    // If this function is being called, it's because we handed out its function
+    // pointer, which only occurs when mDevice has been loaded successfully and
+    // we are permitted to allocate
+
+    int usage = static_cast<int>(descriptor->producerUsage) |
+            static_cast<int>(descriptor->consumerUsage);
+    buffer_handle_t handle = nullptr;
+    int stride = 0;
+    ALOGV("Calling alloc(%p, %u, %u, %i, %u)", mDevice, descriptor->width,
+            descriptor->height, descriptor->format, usage);
+    auto error = mDevice->alloc(mDevice,
+            static_cast<int>(descriptor->width),
+            static_cast<int>(descriptor->height), descriptor->format,
+            usage, &handle, &stride);
+    if (error != 0) {
+        ALOGE("gralloc0 allocation failed: %d (%s)", error,
+                strerror(-error));
+        return GRALLOC1_ERROR_NO_RESOURCES;
+    }
+
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_SET_USAGES,
+            handle,
+            static_cast<int>(descriptor->producerUsage),
+            static_cast<int>(descriptor->consumerUsage));
+
+    uint64_t backingStore = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE,
+            handle, &backingStore);
+    int numFlexPlanes = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES,
+            handle, &numFlexPlanes);
+
+    *outBufferHandle = handle;
+    auto buffer = std::make_shared<Buffer>(handle, backingStore,
+            *descriptor, stride, numFlexPlanes, true);
+
+    std::lock_guard<std::mutex> lock(mBufferMutex);
+    mBuffers.emplace(handle, std::move(buffer));
+
+    return GRALLOC1_ERROR_NONE;
+}
+
+int32_t Gralloc1On0Adapter::allocateHook(gralloc1_device* device,
+        uint32_t numDescriptors,
+        const gralloc1_buffer_descriptor_t* descriptors,
+        buffer_handle_t* outBuffers)
+{
+    if (!outBuffers) {
+        return GRALLOC1_ERROR_UNDEFINED;
+    }
+
+    auto adapter = getAdapter(device);
+
+    gralloc1_error_t error = GRALLOC1_ERROR_NONE;
+    uint32_t i;
+    for (i = 0; i < numDescriptors; i++) {
+        auto descriptor = adapter->getDescriptor(descriptors[i]);
+        if (!descriptor) {
+            error = GRALLOC1_ERROR_BAD_DESCRIPTOR;
+            break;
+        }
+
+        buffer_handle_t bufferHandle = nullptr;
+        error = adapter->allocate(descriptors[i], descriptor, &bufferHandle);
+        if (error != GRALLOC1_ERROR_NONE) {
+            break;
+        }
+
+        outBuffers[i] = bufferHandle;
+    }
+
+    if (error == GRALLOC1_ERROR_NONE) {
+        if (numDescriptors > 1) {
+            error = GRALLOC1_ERROR_NOT_SHARED;
+        }
+    } else {
+        for (uint32_t j = 0; j < i; j++) {
+            adapter->release(adapter->getBuffer(outBuffers[j]));
+            outBuffers[j] = nullptr;
+        }
+    }
+
+    return error;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::retain(
+        const std::shared_ptr<Buffer>& buffer)
+{
+    std::lock_guard<std::mutex> lock(mBufferMutex);
+    buffer->retain();
+    return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::release(
+        const std::shared_ptr<Buffer>& buffer)
+{
+    std::lock_guard<std::mutex> lock(mBufferMutex);
+    if (!buffer->release()) {
+        return GRALLOC1_ERROR_NONE;
+    }
+
+    buffer_handle_t handle = buffer->getHandle();
+    if (buffer->wasAllocated()) {
+        ALOGV("Calling free(%p)", handle);
+        int result = mDevice->free(mDevice, handle);
+        if (result != 0) {
+            ALOGE("gralloc0 free failed: %d", result);
+        }
+    } else {
+        ALOGV("Calling unregisterBuffer(%p)", handle);
+        int result = mModule->unregisterBuffer(mModule, handle);
+        if (result != 0) {
+            ALOGE("gralloc0 unregister failed: %d", result);
+        }
+    }
+
+    mBuffers.erase(handle);
+    return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::retain(buffer_handle_t bufferHandle)
+{
+    ALOGV("retain(%p)", bufferHandle);
+
+    std::lock_guard<std::mutex> lock(mBufferMutex);
+
+    if (mBuffers.count(bufferHandle) != 0) {
+        mBuffers[bufferHandle]->retain();
+        return GRALLOC1_ERROR_NONE;
+    }
+
+    ALOGV("Calling registerBuffer(%p)", bufferHandle);
+    int result = mModule->registerBuffer(mModule, bufferHandle);
+    if (result != 0) {
+        ALOGE("gralloc0 register failed: %d", result);
+        return GRALLOC1_ERROR_NO_RESOURCES;
+    }
+
+    uint64_t backingStore = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE,
+            bufferHandle, &backingStore);
+
+    int numFlexPlanes = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES,
+            bufferHandle, &numFlexPlanes);
+
+    int stride = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_STRIDE,
+            bufferHandle, &stride);
+
+    int width = 0;
+    int height = 0;
+    int format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    int producerUsage = 0;
+    int consumerUsage = 0;
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS,
+            bufferHandle, &width, &height);
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_FORMAT,
+            bufferHandle, &format);
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE,
+            bufferHandle, &producerUsage);
+    mModule->perform(mModule, GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE,
+            bufferHandle, &consumerUsage);
+
+    Descriptor descriptor;
+    descriptor.setDimensions(width, height);
+    descriptor.setFormat(format);
+    descriptor.setProducerUsage(
+            static_cast<gralloc1_producer_usage_t>(producerUsage));
+    descriptor.setConsumerUsage(
+            static_cast<gralloc1_consumer_usage_t>(consumerUsage));
+
+    auto buffer = std::make_shared<Buffer>(bufferHandle, backingStore,
+            descriptor, stride, numFlexPlanes, false);
+    mBuffers.emplace(bufferHandle, std::move(buffer));
+    return GRALLOC1_ERROR_NONE;
+}
+
+static void syncWaitForever(int fd, const char* logname)
+{
+    if (fd < 0) {
+        return;
+    }
+
+    const int warningTimeout = 3500;
+    const int error = sync_wait(fd, warningTimeout);
+    if (error < 0 && errno == ETIME) {
+        ALOGE("%s: fence %d didn't signal in %u ms", logname, fd,
+                warningTimeout);
+        sync_wait(fd, -1);
+    }
+}
+
+gralloc1_error_t Gralloc1On0Adapter::lock(
+        const std::shared_ptr<Buffer>& buffer,
+        gralloc1_producer_usage_t producerUsage,
+        gralloc1_consumer_usage_t consumerUsage,
+        const gralloc1_rect_t& accessRegion, void** outData,
+        int acquireFence)
+{
+    if (mMinorVersion >= 3) {
+        int result = mModule->lockAsync(mModule, buffer->getHandle(),
+                static_cast<int32_t>(producerUsage | consumerUsage),
+                accessRegion.left, accessRegion.top, accessRegion.width,
+                accessRegion.height, outData, acquireFence);
+        if (result != 0) {
+            return GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    } else {
+        syncWaitForever(acquireFence, "Gralloc1On0Adapter::lock");
+
+        int result = mModule->lock(mModule, buffer->getHandle(),
+                static_cast<int32_t>(producerUsage | consumerUsage),
+                accessRegion.left, accessRegion.top, accessRegion.width,
+                accessRegion.height, outData);
+        ALOGV("gralloc0 lock returned %d", result);
+        if (result != 0) {
+            return GRALLOC1_ERROR_UNSUPPORTED;
+        } else if (acquireFence >= 0) {
+            close(acquireFence);
+        }
+    }
+    return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::lockFlex(
+        const std::shared_ptr<Buffer>& buffer,
+        gralloc1_producer_usage_t producerUsage,
+        gralloc1_consumer_usage_t consumerUsage,
+        const gralloc1_rect_t& accessRegion,
+        struct android_flex_layout* outFlex,
+        int acquireFence)
+{
+    if (mMinorVersion >= 3) {
+        int result = mModule->perform(mModule,
+                GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX,
+                buffer->getHandle(),
+                static_cast<int>(producerUsage),
+                static_cast<int>(consumerUsage),
+                accessRegion.left,
+                accessRegion.top,
+                accessRegion.width,
+                accessRegion.height,
+                outFlex, acquireFence);
+        if (result != 0) {
+            return GRALLOC1_ERROR_UNSUPPORTED;
+        }
+    } else {
+        syncWaitForever(acquireFence, "Gralloc1On0Adapter::lockFlex");
+
+        int result = mModule->perform(mModule,
+                GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX,
+                buffer->getHandle(),
+                static_cast<int>(producerUsage),
+                static_cast<int>(consumerUsage),
+                accessRegion.left,
+                accessRegion.top,
+                accessRegion.width,
+                accessRegion.height,
+                outFlex, -1);
+        if (result != 0) {
+            return GRALLOC1_ERROR_UNSUPPORTED;
+        } else if (acquireFence >= 0) {
+            close(acquireFence);
+        }
+    }
+
+    return GRALLOC1_ERROR_NONE;
+}
+
+gralloc1_error_t Gralloc1On0Adapter::unlock(
+        const std::shared_ptr<Buffer>& buffer,
+        int* outReleaseFence)
+{
+    if (mMinorVersion >= 3) {
+        int fenceFd = -1;
+        int result = mModule->unlockAsync(mModule, buffer->getHandle(),
+                &fenceFd);
+        if (result != 0) {
+            close(fenceFd);
+            ALOGE("gralloc0 unlockAsync failed: %d", result);
+        } else {
+            *outReleaseFence = fenceFd;
+        }
+    } else {
+        int result = mModule->unlock(mModule, buffer->getHandle());
+        if (result != 0) {
+            ALOGE("gralloc0 unlock failed: %d", result);
+        } else {
+            *outReleaseFence = -1;
+        }
+    }
+    return GRALLOC1_ERROR_NONE;
+}
+
+std::shared_ptr<Gralloc1On0Adapter::Descriptor>
+Gralloc1On0Adapter::getDescriptor(gralloc1_buffer_descriptor_t descriptorId)
+{
+    std::lock_guard<std::mutex> lock(mDescriptorMutex);
+    if (mDescriptors.count(descriptorId) == 0) {
+        return nullptr;
+    }
+
+    return mDescriptors[descriptorId];
+}
+
+std::shared_ptr<Gralloc1On0Adapter::Buffer> Gralloc1On0Adapter::getBuffer(
+        buffer_handle_t bufferHandle)
+{
+    std::lock_guard<std::mutex> lock(mBufferMutex);
+    if (mBuffers.count(bufferHandle) == 0) {
+        return nullptr;
+    }
+
+    return mBuffers[bufferHandle];
+}
+
+std::atomic<gralloc1_buffer_descriptor_t>
+        Gralloc1On0Adapter::sNextBufferDescriptorId(1);
+
+} // namespace hardware
+} // namespace android
diff --git a/graphics/allocator/2.0/default/Gralloc1On0Adapter.h b/graphics/allocator/2.0/default/Gralloc1On0Adapter.h
new file mode 100644
index 0000000..180015d
--- /dev/null
+++ b/graphics/allocator/2.0/default/Gralloc1On0Adapter.h
@@ -0,0 +1,458 @@
+/*
+ * 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_GRALLOC_1_ON_0_ADAPTER_H
+#define ANDROID_HARDWARE_GRALLOC_1_ON_0_ADAPTER_H
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <unordered_map>
+#include <utility>
+
+struct gralloc_module_t;
+struct alloc_device_t;
+
+namespace android {
+namespace hardware {
+
+class Gralloc1On0Adapter : public gralloc1_device_t
+{
+public:
+    Gralloc1On0Adapter(const hw_module_t* module);
+    ~Gralloc1On0Adapter();
+
+    gralloc1_device_t* getDevice() {
+        return static_cast<gralloc1_device_t*>(this);
+    }
+
+private:
+    static inline Gralloc1On0Adapter* getAdapter(gralloc1_device_t* device) {
+        return static_cast<Gralloc1On0Adapter*>(device);
+    }
+
+    static int closeHook(struct hw_device_t* device) {
+        delete getAdapter(reinterpret_cast<gralloc1_device_t*>(device));
+        return 0;
+    }
+
+    // getCapabilities
+
+    void doGetCapabilities(uint32_t* outCount,
+            int32_t* /*gralloc1_capability_t*/ outCapabilities);
+    static void getCapabilitiesHook(gralloc1_device_t* device,
+            uint32_t* outCount,
+            int32_t* /*gralloc1_capability_t*/ outCapabilities) {
+        getAdapter(device)->doGetCapabilities(outCount, outCapabilities);
+    }
+
+    // getFunction
+
+    gralloc1_function_pointer_t doGetFunction(
+            int32_t /*gralloc1_function_descriptor_t*/ descriptor);
+    static gralloc1_function_pointer_t getFunctionHook(
+            gralloc1_device_t* device,
+            int32_t /*gralloc1_function_descriptor_t*/ descriptor) {
+        return getAdapter(device)->doGetFunction(descriptor);
+    }
+
+    // dump
+
+    void dump(uint32_t* outSize, char* outBuffer);
+    static void dumpHook(gralloc1_device_t* device, uint32_t* outSize,
+            char* outBuffer) {
+        return getAdapter(device)->dump(outSize, outBuffer);
+    }
+    std::string mCachedDump;
+
+    // Buffer descriptor lifecycle functions
+
+    struct Descriptor;
+
+    gralloc1_error_t createDescriptor(
+            gralloc1_buffer_descriptor_t* outDescriptor);
+    static int32_t createDescriptorHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t* outDescriptor) {
+        auto error = getAdapter(device)->createDescriptor(outDescriptor);
+        return static_cast<int32_t>(error);
+    }
+
+    gralloc1_error_t destroyDescriptor(gralloc1_buffer_descriptor_t descriptor);
+    static int32_t destroyDescriptorHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptor) {
+        auto error = getAdapter(device)->destroyDescriptor(descriptor);
+        return static_cast<int32_t>(error);
+    }
+
+    // Buffer descriptor modification functions
+
+    struct Descriptor : public std::enable_shared_from_this<Descriptor> {
+        Descriptor()
+          : width(0),
+            height(0),
+            format(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED),
+            layerCount(1),
+            producerUsage(GRALLOC1_PRODUCER_USAGE_NONE),
+            consumerUsage(GRALLOC1_CONSUMER_USAGE_NONE) {}
+
+        gralloc1_error_t setDimensions(uint32_t w, uint32_t h) {
+            width = w;
+            height = h;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t setFormat(int32_t f) {
+            format = f;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t setLayerCount(uint32_t lc) {
+            layerCount = lc;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t setProducerUsage(gralloc1_producer_usage_t usage) {
+            producerUsage = usage;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t setConsumerUsage(gralloc1_consumer_usage_t usage) {
+            consumerUsage = usage;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        uint32_t width;
+        uint32_t height;
+        int32_t format;
+        uint32_t layerCount;
+        gralloc1_producer_usage_t producerUsage;
+        gralloc1_consumer_usage_t consumerUsage;
+    };
+
+    template <typename ...Args>
+    static int32_t callDescriptorFunction(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId,
+            gralloc1_error_t (Descriptor::*member)(Args...), Args... args) {
+        auto descriptor = getAdapter(device)->getDescriptor(descriptorId);
+        if (!descriptor) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_DESCRIPTOR);
+        }
+        auto error = ((*descriptor).*member)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    static int32_t setConsumerUsageHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) {
+        auto usage = static_cast<gralloc1_consumer_usage_t>(intUsage);
+        return callDescriptorFunction(device, descriptorId,
+                &Descriptor::setConsumerUsage, usage);
+    }
+
+    static int32_t setDimensionsHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId, uint32_t width,
+            uint32_t height) {
+        return callDescriptorFunction(device, descriptorId,
+                &Descriptor::setDimensions, width, height);
+    }
+
+    static int32_t setFormatHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId, int32_t format) {
+        return callDescriptorFunction(device, descriptorId,
+                &Descriptor::setFormat, format);
+    }
+
+    static int32_t setLayerCountHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId, uint32_t layerCount) {
+        return callDescriptorFunction(device, descriptorId,
+                &Descriptor::setLayerCount, layerCount);
+    }
+
+    static int32_t setProducerUsageHook(gralloc1_device_t* device,
+            gralloc1_buffer_descriptor_t descriptorId, uint64_t intUsage) {
+        auto usage = static_cast<gralloc1_producer_usage_t>(intUsage);
+        return callDescriptorFunction(device, descriptorId,
+                &Descriptor::setProducerUsage, usage);
+    }
+
+    // Buffer handle query functions
+
+    class Buffer {
+    public:
+        Buffer(buffer_handle_t handle, gralloc1_backing_store_t store,
+                const Descriptor& descriptor, uint32_t stride,
+                uint32_t numFlexPlanes, bool wasAllocated);
+
+        buffer_handle_t getHandle() const { return mHandle; }
+
+        void retain() { ++mReferenceCount; }
+
+        // Returns true if the reference count has dropped to 0, indicating that
+        // the buffer needs to be released
+        bool release() { return --mReferenceCount == 0; }
+
+        bool wasAllocated() const { return mWasAllocated; }
+
+        gralloc1_error_t getBackingStore(
+                gralloc1_backing_store_t* outStore) const {
+            *outStore = mStore;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getConsumerUsage(
+                gralloc1_consumer_usage_t* outUsage) const {
+            *outUsage = mDescriptor.consumerUsage;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getDimensions(uint32_t* outWidth,
+                uint32_t* outHeight) const {
+            *outWidth = mDescriptor.width;
+            *outHeight = mDescriptor.height;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getFormat(int32_t* outFormat) const {
+            *outFormat = mDescriptor.format;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getLayerCount(uint32_t* outLayerCount) const {
+            *outLayerCount = mDescriptor.layerCount;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getNumFlexPlanes(uint32_t* outNumPlanes) const {
+            *outNumPlanes = mNumFlexPlanes;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getProducerUsage(
+                gralloc1_producer_usage_t* outUsage) const {
+            *outUsage = mDescriptor.producerUsage;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+        gralloc1_error_t getStride(uint32_t* outStride) const {
+            *outStride = mStride;
+            return GRALLOC1_ERROR_NONE;
+        }
+
+    private:
+
+        const buffer_handle_t mHandle;
+        size_t mReferenceCount;
+
+        const gralloc1_backing_store_t mStore;
+        const Descriptor mDescriptor;
+        const uint32_t mStride;
+        const uint32_t mNumFlexPlanes;
+
+        // Whether this buffer allocated in this process (as opposed to just
+        // being retained here), which determines whether to free or unregister
+        // the buffer when this Buffer is released
+        const bool mWasAllocated;
+    };
+
+    template <typename ...Args>
+    static int32_t callBufferFunction(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle,
+            gralloc1_error_t (Buffer::*member)(Args...) const, Args... args) {
+        auto buffer = getAdapter(device)->getBuffer(bufferHandle);
+        if (!buffer) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
+        }
+        auto error = ((*buffer).*member)(std::forward<Args>(args)...);
+        return static_cast<int32_t>(error);
+    }
+
+    template <typename MF, MF memFunc, typename ...Args>
+    static int32_t bufferHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle, Args... args) {
+        return Gralloc1On0Adapter::callBufferFunction(device, bufferHandle,
+                memFunc, std::forward<Args>(args)...);
+    }
+
+    static int32_t getConsumerUsageHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle, uint64_t* outUsage) {
+        auto usage = GRALLOC1_CONSUMER_USAGE_NONE;
+        auto error = callBufferFunction(device, bufferHandle,
+                &Buffer::getConsumerUsage, &usage);
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outUsage = static_cast<uint64_t>(usage);
+        }
+        return error;
+    }
+
+    static int32_t getProducerUsageHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle, uint64_t* outUsage) {
+        auto usage = GRALLOC1_PRODUCER_USAGE_NONE;
+        auto error = callBufferFunction(device, bufferHandle,
+                &Buffer::getProducerUsage, &usage);
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outUsage = static_cast<uint64_t>(usage);
+        }
+        return error;
+    }
+
+    // Buffer management functions
+
+    gralloc1_error_t allocate(
+            gralloc1_buffer_descriptor_t id,
+            const std::shared_ptr<Descriptor>& descriptor,
+            buffer_handle_t* outBufferHandle);
+    static int32_t allocateHook(gralloc1_device* device,
+            uint32_t numDescriptors,
+            const gralloc1_buffer_descriptor_t* descriptors,
+            buffer_handle_t* outBuffers);
+
+    gralloc1_error_t retain(const std::shared_ptr<Buffer>& buffer);
+    gralloc1_error_t retain(buffer_handle_t bufferHandle);
+    static int32_t retainHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle)
+    {
+        auto adapter = getAdapter(device);
+        return adapter->retain(bufferHandle);
+    }
+
+    gralloc1_error_t release(const std::shared_ptr<Buffer>& buffer);
+    static int32_t releaseHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle) {
+        auto adapter = getAdapter(device);
+
+        auto buffer = adapter->getBuffer(bufferHandle);
+        if (!buffer) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
+        }
+
+        auto error = adapter->release(buffer);
+        return static_cast<int32_t>(error);
+    }
+
+    // Buffer access functions
+
+    gralloc1_error_t lock(const std::shared_ptr<Buffer>& buffer,
+            gralloc1_producer_usage_t producerUsage,
+            gralloc1_consumer_usage_t consumerUsage,
+            const gralloc1_rect_t& accessRegion, void** outData,
+            int acquireFence);
+    gralloc1_error_t lockFlex(const std::shared_ptr<Buffer>& buffer,
+            gralloc1_producer_usage_t producerUsage,
+            gralloc1_consumer_usage_t consumerUsage,
+            const gralloc1_rect_t& accessRegion,
+            struct android_flex_layout* outFlex,
+            int acquireFence);
+
+    template <typename OUT, gralloc1_error_t (Gralloc1On0Adapter::*member)(
+            const std::shared_ptr<Buffer>&, gralloc1_producer_usage_t,
+            gralloc1_consumer_usage_t, const gralloc1_rect_t&, OUT*,
+            int)>
+    static int32_t lockHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle,
+            uint64_t /*gralloc1_producer_usage_t*/ uintProducerUsage,
+            uint64_t /*gralloc1_consumer_usage_t*/ uintConsumerUsage,
+            const gralloc1_rect_t* accessRegion, OUT* outData,
+            int32_t acquireFenceFd) {
+        auto adapter = getAdapter(device);
+
+        // Exactly one of producer and consumer usage must be *_USAGE_NONE,
+        // but we can't check this until the upper levels of the framework
+        // correctly distinguish between producer and consumer usage
+        /*
+        bool hasProducerUsage =
+                uintProducerUsage != GRALLOC1_PRODUCER_USAGE_NONE;
+        bool hasConsumerUsage =
+                uintConsumerUsage != GRALLOC1_CONSUMER_USAGE_NONE;
+        if (hasProducerUsage && hasConsumerUsage ||
+                !hasProducerUsage && !hasConsumerUsage) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
+        }
+        */
+
+        auto producerUsage =
+                static_cast<gralloc1_producer_usage_t>(uintProducerUsage);
+        auto consumerUsage =
+                static_cast<gralloc1_consumer_usage_t>(uintConsumerUsage);
+
+        if (!outData) {
+            const auto producerCpuUsage = GRALLOC1_PRODUCER_USAGE_CPU_READ |
+                    GRALLOC1_PRODUCER_USAGE_CPU_WRITE;
+            if ((producerUsage & producerCpuUsage) != 0) {
+                return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
+            }
+            if ((consumerUsage & GRALLOC1_CONSUMER_USAGE_CPU_READ) != 0) {
+                return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
+            }
+        }
+
+        auto buffer = adapter->getBuffer(bufferHandle);
+        if (!buffer) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
+        }
+
+        if (!accessRegion) {
+            ALOGE("accessRegion is null");
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_VALUE);
+        }
+
+        auto error = ((*adapter).*member)(buffer, producerUsage, consumerUsage,
+                *accessRegion, outData, acquireFenceFd);
+        return static_cast<int32_t>(error);
+    }
+
+    gralloc1_error_t unlock(const std::shared_ptr<Buffer>& buffer,
+            int* outReleaseFence);
+    static int32_t unlockHook(gralloc1_device_t* device,
+            buffer_handle_t bufferHandle, int32_t* outReleaseFenceFd) {
+        auto adapter = getAdapter(device);
+
+        auto buffer = adapter->getBuffer(bufferHandle);
+        if (!buffer) {
+            return static_cast<int32_t>(GRALLOC1_ERROR_BAD_HANDLE);
+        }
+
+        int releaseFence = -1;
+        auto error = adapter->unlock(buffer, &releaseFence);
+        if (error == GRALLOC1_ERROR_NONE) {
+            *outReleaseFenceFd = releaseFence;
+        }
+        return static_cast<int32_t>(error);
+    }
+
+    // Adapter internals
+    const gralloc_module_t* mModule;
+    uint8_t mMinorVersion;
+    alloc_device_t* mDevice;
+
+    std::shared_ptr<Descriptor> getDescriptor(
+            gralloc1_buffer_descriptor_t descriptorId);
+    std::shared_ptr<Buffer> getBuffer(buffer_handle_t bufferHandle);
+
+    static std::atomic<gralloc1_buffer_descriptor_t> sNextBufferDescriptorId;
+    std::mutex mDescriptorMutex;
+    std::unordered_map<gralloc1_buffer_descriptor_t,
+            std::shared_ptr<Descriptor>> mDescriptors;
+    std::mutex mBufferMutex;
+    std::unordered_map<buffer_handle_t, std::shared_ptr<Buffer>> mBuffers;
+};
+
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRALLOC_1_ON_0_ADAPTER_H
diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
new file mode 100644
index 0000000..8bb0d85
--- /dev/null
+++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
@@ -0,0 +1,5 @@
+service gralloc-2-0 /system/bin/hw/android.hardware.graphics.allocator@2.0-service
+    class hal
+    user system
+    group graphics drmrpc readproc
+    onrestart restart surfaceflinger
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.cpp b/graphics/allocator/2.0/default/gralloc1-adapter.cpp
new file mode 100644
index 0000000..fcc59cd
--- /dev/null
+++ b/graphics/allocator/2.0/default/gralloc1-adapter.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "Gralloc1On0Adapter.h"
+#include "gralloc1-adapter.h"
+
+int gralloc1_adapter_device_open(const struct hw_module_t* module,
+        const char* id, struct hw_device_t** device)
+{
+    if (strcmp(id, GRALLOC_HARDWARE_MODULE_ID) != 0) {
+        ALOGE("unknown gralloc1 device id: %s", id);
+        return -EINVAL;
+    }
+
+    auto adapter_device = new android::hardware::Gralloc1On0Adapter(module);
+    *device = &adapter_device->common;
+
+    return 0;
+}
diff --git a/graphics/allocator/2.0/default/gralloc1-adapter.h b/graphics/allocator/2.0/default/gralloc1-adapter.h
new file mode 100644
index 0000000..b912ef6
--- /dev/null
+++ b/graphics/allocator/2.0/default/gralloc1-adapter.h
@@ -0,0 +1,89 @@
+/*
+ * 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_GRALLOC1_ADAPTER_H
+#define ANDROID_HARDWARE_GRALLOC1_ADAPTER_H
+
+#include <hardware/hardware.h>
+
+__BEGIN_DECLS
+
+#define GRALLOC1_ADAPTER_MODULE_API_VERSION_1_0 \
+    HARDWARE_MODULE_API_VERSION(1, 0)
+
+enum {
+    GRALLOC1_ADAPTER_PERFORM_FIRST = 10000,
+
+    // void getRealModuleApiVersionMinor(..., int* outMinorVersion);
+    GRALLOC1_ADAPTER_PERFORM_GET_REAL_MODULE_API_VERSION_MINOR =
+        GRALLOC1_ADAPTER_PERFORM_FIRST,
+
+    // void setUsages(..., buffer_handle_t buffer,
+    //                     int producerUsage,
+    //                     int consumerUsage);
+    GRALLOC1_ADAPTER_PERFORM_SET_USAGES =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 1,
+
+    // void getDimensions(..., buffer_handle_t buffer,
+    //                         int* outWidth,
+    //                         int* outHeight);
+    GRALLOC1_ADAPTER_PERFORM_GET_DIMENSIONS =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 2,
+
+    // void getFormat(..., buffer_handle_t buffer, int* outFormat);
+    GRALLOC1_ADAPTER_PERFORM_GET_FORMAT =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 3,
+
+    // void getProducerUsage(..., buffer_handle_t buffer, int* outUsage);
+    GRALLOC1_ADAPTER_PERFORM_GET_PRODUCER_USAGE =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 4,
+
+    // void getConsumerUsage(..., buffer_handle_t buffer, int* outUsage);
+    GRALLOC1_ADAPTER_PERFORM_GET_CONSUMER_USAGE =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 5,
+
+    // void getBackingStore(..., buffer_handle_t buffer,
+    //                           uint64_t* outBackingStore);
+    GRALLOC1_ADAPTER_PERFORM_GET_BACKING_STORE =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 6,
+
+    // void getNumFlexPlanes(..., buffer_handle_t buffer,
+    //                            int* outNumFlexPlanes);
+    GRALLOC1_ADAPTER_PERFORM_GET_NUM_FLEX_PLANES =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 7,
+
+    // void getStride(..., buffer_handle_t buffer, int* outStride);
+    GRALLOC1_ADAPTER_PERFORM_GET_STRIDE =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 8,
+
+    // void lockFlex(..., buffer_handle_t buffer,
+    //                    int producerUsage,
+    //                    int consumerUsage,
+    //                    int left,
+    //                    int top,
+    //                    int width,
+    //                    int height,
+    //                    android_flex_layout* outLayout,
+    //                    int acquireFence);
+    GRALLOC1_ADAPTER_PERFORM_LOCK_FLEX =
+        GRALLOC1_ADAPTER_PERFORM_FIRST + 9,
+};
+
+int gralloc1_adapter_device_open(const struct hw_module_t* module,
+        const char* id, struct hw_device_t** device);
+
+__END_DECLS
+
+#endif /* ANDROID_HARDWARE_GRALLOC1_ADAPTER_H */
diff --git a/graphics/allocator/2.0/default/service.cpp b/graphics/allocator/2.0/default/service.cpp
new file mode 100644
index 0000000..525b342
--- /dev/null
+++ b/graphics/allocator/2.0/default/service.cpp
@@ -0,0 +1,28 @@
+/*
+ * 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 "android.hardware.graphics.allocator@2.0-service"
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::hardware::graphics::allocator::V2_0::IAllocator;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IAllocator>("gralloc");
+}
diff --git a/graphics/allocator/2.0/types.hal b/graphics/allocator/2.0/types.hal
new file mode 100644
index 0000000..f9d1e1b
--- /dev/null
+++ b/graphics/allocator/2.0/types.hal
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.allocator@2.0;
+
+enum Error : int32_t {
+    NONE            = 0, /* no error */
+    BAD_DESCRIPTOR  = 1, /* invalid BufferDescriptor */
+    BAD_BUFFER      = 2, /* invalid Buffer */
+    BAD_VALUE       = 3, /* invalid width, height, etc. */
+    NOT_SHARED      = 4, /* buffers not sharing backing store */
+    NO_RESOURCES    = 5, /* temporary failure due to resource contention */
+    UNDEFINED       = 6, /* an operation has no defined meaning */
+    UNSUPPORTED     = 7, /* permanent failure */
+};
+
+enum ProducerUsage : uint64_t {
+    /* bit 0 is reserved */
+
+    /* buffer is read by CPU occasionally */
+    CPU_READ        = 1ULL << 1,
+    /* buffer is read by CPU frequently */
+    CPU_READ_OFTEN  = 1ULL << 2,
+
+    /* bit 3 is reserved */
+    /* bit 4 is reserved */
+
+    /* buffer is written by CPU occasionally */
+    CPU_WRITE       = 1ULL << 5,
+    /* buffer is written by CPU frequently */
+    CPU_WRITE_OFTEN = 1ULL << 6,
+
+    /* bit 7 is reserved */
+    /* bit 8 is reserved */
+
+    /* buffer is used as a GPU render target */
+    GPU_RENDER_TARGET = 1ULL << 9,
+
+    /* bit 10 is reserved */
+    /* bit 11 is reserved */
+    /* bit 12 is reserved */
+    /* bit 13 is reserved */
+
+    /*
+     * Buffer is allocated with hardware-level protection against copying the
+     * contents (or information derived from the contents) into unprotected
+     * memory.
+     */
+    PROTECTED         = 1ULL << 14,
+
+    /* bit 15 is reserved */
+    /* bit 16 is reserved */
+
+    /* buffer is used as a camera HAL output */
+    CAMERA            = 1ULL << 17,
+
+    /* bit 18 is reserved */
+    /* bit 19 is reserved */
+    /* bit 20 is reserved */
+    /* bit 21 is reserved */
+
+    /* buffer is used as a video decoder output */
+    VIDEO_DECODER     = 1ULL << 22,
+
+    /* buffer is used as a sensor direct report output */
+    SENSOR_DIRECT_DATA = 1ULL << 23,
+
+    /* bits 24-27 are reserved for future versions */
+    /* bits 28-31 are reserved for vendor extensions */
+
+    /* bits 32-47 are reserved for future versions */
+    /* bits 48-63 are reserved for vendor extensions */
+};
+
+enum ConsumerUsage : uint64_t {
+    /* bit 0 is reserved */
+
+    /* buffer is read by CPU occasionally */
+    CPU_READ          = 1ULL << 1,
+    /* buffer is read by CPU frequently */
+    CPU_READ_OFTEN    = 1ULL << 2,
+
+    /* bit 3 is reserved */
+    /* bit 4 is reserved */
+    /* bit 5 is reserved */
+    /* bit 6 is reserved */
+    /* bit 7 is reserved */
+
+    /* buffer is used as a GPU texture */
+    GPU_TEXTURE       = 1ULL << 8,
+
+    /* bit 9 is reserved */
+    /* bit 10 is reserved */
+
+    /* buffer is used by hwcomposer HAL */
+    HWCOMPOSER        = 1ULL << 11,
+    /* buffer is a hwcomposer HAL client target */
+    CLIENT_TARGET     = 1ULL << 12,
+
+    /* bit 13 is reserved */
+    /* bit 14 is reserved */
+
+    /* buffer is used as a hwcomposer HAL cursor */
+    CURSOR            = 1ULL << 15,
+
+    /* buffer is used as a video encoder input */
+    VIDEO_ENCODER     = 1ULL << 16,
+
+    /* bit 17 is reserved */
+
+    /* buffer is used as a camera HAL input */
+    CAMERA            = 1ULL << 18,
+
+    /* bit 19 is reserved */
+
+    /* buffer is used as a renderscript allocation */
+    RENDERSCRIPT      = 1ULL << 20,
+
+    /* bit 21 is reserved */
+    /* bit 22 is reserved */
+
+    /* buffer is used as as an OpenGL shader storage or uniform
+       buffer object */
+    GPU_DATA_BUFFER    = 1ULL << 23,
+
+    /* bits 24-27 are reserved for future versions */
+    /* bits 28-31 are reserved for vendor extensions */
+
+    /* bits 32-47 are reserved for future versions */
+    /* bits 48-63 are reserved for vendor extensions */
+};
+
+typedef uint64_t BufferDescriptor;
+typedef uint64_t Buffer;
diff --git a/graphics/allocator/2.0/vts/Allocator.vts b/graphics/allocator/2.0/vts/Allocator.vts
new file mode 100644
index 0000000..e767cbd
--- /dev/null
+++ b/graphics/allocator/2.0/vts/Allocator.vts
@@ -0,0 +1,87 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "IAllocator"
+
+package: "android.hardware.graphics.allocator"
+
+import: "android.hardware.graphics.allocator@2.0::IAllocatorClient"
+import: "android.hardware.graphics.allocator@2.0::types"
+
+interface: {
+    attribute: {
+        name: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "INVALID"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "TEST_ALLOCATE"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "LAYERED_BUFFERS"
+            scalar_value: {
+                int32_t: 2
+            }
+        }
+    }
+
+    api: {
+        name: "getCapabilities"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_ENUM
+                predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocator::Capability"
+            }
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "dumpDebugInfo"
+        return_type_hidl: {
+            type: TYPE_STRING
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "createClient"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_HIDL_INTERFACE
+            predefined_type: "IAllocatorClient"
+            is_callback: false
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+}
diff --git a/graphics/allocator/2.0/vts/AllocatorClient.vts b/graphics/allocator/2.0/vts/AllocatorClient.vts
new file mode 100644
index 0000000..2ab19f7
--- /dev/null
+++ b/graphics/allocator/2.0/vts/AllocatorClient.vts
@@ -0,0 +1,635 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "IAllocatorClient"
+
+package: "android.hardware.graphics.allocator"
+
+import: "android.hardware.graphics.allocator@2.0::types"
+import: "android.hardware.graphics.common@1.0::types"
+
+interface: {
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::PixelFormat"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "RGBA_8888"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "RGBX_8888"
+            scalar_value: {
+                int32_t: 2
+            }
+            enumerator: "RGB_888"
+            scalar_value: {
+                int32_t: 3
+            }
+            enumerator: "RGB_565"
+            scalar_value: {
+                int32_t: 4
+            }
+            enumerator: "BGRA_8888"
+            scalar_value: {
+                int32_t: 5
+            }
+            enumerator: "RGBA_FP16"
+            scalar_value: {
+                int32_t: 22
+            }
+            enumerator: "YV12"
+            scalar_value: {
+                int32_t: 842094169
+            }
+            enumerator: "Y8"
+            scalar_value: {
+                int32_t: 538982489
+            }
+            enumerator: "Y16"
+            scalar_value: {
+                int32_t: 540422489
+            }
+            enumerator: "RAW16"
+            scalar_value: {
+                int32_t: 32
+            }
+            enumerator: "RAW10"
+            scalar_value: {
+                int32_t: 37
+            }
+            enumerator: "RAW12"
+            scalar_value: {
+                int32_t: 38
+            }
+            enumerator: "RAW_OPAQUE"
+            scalar_value: {
+                int32_t: 36
+            }
+            enumerator: "BLOB"
+            scalar_value: {
+                int32_t: 33
+            }
+            enumerator: "IMPLEMENTATION_DEFINED"
+            scalar_value: {
+                int32_t: 34
+            }
+            enumerator: "YCBCR_420_888"
+            scalar_value: {
+                int32_t: 35
+            }
+            enumerator: "YCBCR_422_888"
+            scalar_value: {
+                int32_t: 39
+            }
+            enumerator: "YCBCR_444_888"
+            scalar_value: {
+                int32_t: 40
+            }
+            enumerator: "FLEX_RGB_888"
+            scalar_value: {
+                int32_t: 41
+            }
+            enumerator: "FLEX_RGBA_8888"
+            scalar_value: {
+                int32_t: 42
+            }
+            enumerator: "YCBCR_422_SP"
+            scalar_value: {
+                int32_t: 16
+            }
+            enumerator: "YCRCB_420_SP"
+            scalar_value: {
+                int32_t: 17
+            }
+            enumerator: "YCBCR_422_I"
+            scalar_value: {
+                int32_t: 20
+            }
+            enumerator: "JPEG"
+            scalar_value: {
+                int32_t: 256
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::Transform"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "FLIP_H"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "FLIP_V"
+            scalar_value: {
+                int32_t: 2
+            }
+            enumerator: "ROT_90"
+            scalar_value: {
+                int32_t: 4
+            }
+            enumerator: "ROT_180"
+            scalar_value: {
+                int32_t: 3
+            }
+            enumerator: "ROT_270"
+            scalar_value: {
+                int32_t: 7
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::Dataspace"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "UNKNOWN"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "ARBITRARY"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "STANDARD_SHIFT"
+            scalar_value: {
+                int32_t: 16
+            }
+            enumerator: "STANDARD_MASK"
+            scalar_value: {
+                int32_t: 4128768
+            }
+            enumerator: "STANDARD_UNSPECIFIED"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "STANDARD_BT709"
+            scalar_value: {
+                int32_t: 65536
+            }
+            enumerator: "STANDARD_BT601_625"
+            scalar_value: {
+                int32_t: 131072
+            }
+            enumerator: "STANDARD_BT601_625_UNADJUSTED"
+            scalar_value: {
+                int32_t: 196608
+            }
+            enumerator: "STANDARD_BT601_525"
+            scalar_value: {
+                int32_t: 262144
+            }
+            enumerator: "STANDARD_BT601_525_UNADJUSTED"
+            scalar_value: {
+                int32_t: 327680
+            }
+            enumerator: "STANDARD_BT2020"
+            scalar_value: {
+                int32_t: 393216
+            }
+            enumerator: "STANDARD_BT2020_CONSTANT_LUMINANCE"
+            scalar_value: {
+                int32_t: 458752
+            }
+            enumerator: "STANDARD_BT470M"
+            scalar_value: {
+                int32_t: 524288
+            }
+            enumerator: "STANDARD_FILM"
+            scalar_value: {
+                int32_t: 589824
+            }
+            enumerator: "STANDARD_DCI_P3"
+            scalar_value: {
+                int32_t: 655360
+            }
+            enumerator: "STANDARD_ADOBE_RGB"
+            scalar_value: {
+                int32_t: 720896
+            }
+            enumerator: "TRANSFER_SHIFT"
+            scalar_value: {
+                int32_t: 22
+            }
+            enumerator: "TRANSFER_MASK"
+            scalar_value: {
+                int32_t: 130023424
+            }
+            enumerator: "TRANSFER_UNSPECIFIED"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "TRANSFER_LINEAR"
+            scalar_value: {
+                int32_t: 4194304
+            }
+            enumerator: "TRANSFER_SRGB"
+            scalar_value: {
+                int32_t: 8388608
+            }
+            enumerator: "TRANSFER_SMPTE_170M"
+            scalar_value: {
+                int32_t: 12582912
+            }
+            enumerator: "TRANSFER_GAMMA2_2"
+            scalar_value: {
+                int32_t: 16777216
+            }
+            enumerator: "TRANSFER_GAMMA2_6"
+            scalar_value: {
+                int32_t: 20971520
+            }
+            enumerator: "TRANSFER_GAMMA2_8"
+            scalar_value: {
+                int32_t: 25165824
+            }
+            enumerator: "TRANSFER_ST2084"
+            scalar_value: {
+                int32_t: 29360128
+            }
+            enumerator: "TRANSFER_HLG"
+            scalar_value: {
+                int32_t: 33554432
+            }
+            enumerator: "RANGE_SHIFT"
+            scalar_value: {
+                int32_t: 27
+            }
+            enumerator: "RANGE_MASK"
+            scalar_value: {
+                int32_t: 939524096
+            }
+            enumerator: "RANGE_UNSPECIFIED"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "RANGE_FULL"
+            scalar_value: {
+                int32_t: 134217728
+            }
+            enumerator: "RANGE_LIMITED"
+            scalar_value: {
+                int32_t: 268435456
+            }
+            enumerator: "RANGE_EXTENDED"
+            scalar_value: {
+                int32_t: 402653184
+            }
+            enumerator: "SRGB_LINEAR"
+            scalar_value: {
+                int32_t: 512
+            }
+            enumerator: "V0_SRGB_LINEAR"
+            scalar_value: {
+                int32_t: 138477568
+            }
+            enumerator: "V0_SCRGB_LINEAR"
+            scalar_value: {
+                int32_t: 406913024
+            }
+            enumerator: "SRGB"
+            scalar_value: {
+                int32_t: 513
+            }
+            enumerator: "V0_SRGB"
+            scalar_value: {
+                int32_t: 142671872
+            }
+            enumerator: "V0_SCRGB"
+            scalar_value: {
+                int32_t: 411107328
+            }
+            enumerator: "JFIF"
+            scalar_value: {
+                int32_t: 257
+            }
+            enumerator: "V0_JFIF"
+            scalar_value: {
+                int32_t: 146931712
+            }
+            enumerator: "BT601_625"
+            scalar_value: {
+                int32_t: 258
+            }
+            enumerator: "V0_BT601_625"
+            scalar_value: {
+                int32_t: 281149440
+            }
+            enumerator: "BT601_525"
+            scalar_value: {
+                int32_t: 259
+            }
+            enumerator: "V0_BT601_525"
+            scalar_value: {
+                int32_t: 281280512
+            }
+            enumerator: "BT709"
+            scalar_value: {
+                int32_t: 260
+            }
+            enumerator: "V0_BT709"
+            scalar_value: {
+                int32_t: 281083904
+            }
+            enumerator: "DCI_P3_LINEAR"
+            scalar_value: {
+                int32_t: 139067392
+            }
+            enumerator: "DCI_P3"
+            scalar_value: {
+                int32_t: 155844608
+            }
+            enumerator: "DISPLAY_P3_LINEAR"
+            scalar_value: {
+                int32_t: 139067392
+            }
+            enumerator: "DISPLAY_P3"
+            scalar_value: {
+                int32_t: 143261696
+            }
+            enumerator: "ADOBE_RGB"
+            scalar_value: {
+                int32_t: 151715840
+            }
+            enumerator: "BT2020_LINEAR"
+            scalar_value: {
+                int32_t: 138805248
+            }
+            enumerator: "BT2020"
+            scalar_value: {
+                int32_t: 147193856
+            }
+            enumerator: "DEPTH"
+            scalar_value: {
+                int32_t: 4096
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::ColorMode"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "NATIVE"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "STANDARD_BT601_625"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "STANDARD_BT601_625_UNADJUSTED"
+            scalar_value: {
+                int32_t: 2
+            }
+            enumerator: "STANDARD_BT601_525"
+            scalar_value: {
+                int32_t: 3
+            }
+            enumerator: "STANDARD_BT601_525_UNADJUSTED"
+            scalar_value: {
+                int32_t: 4
+            }
+            enumerator: "STANDARD_BT709"
+            scalar_value: {
+                int32_t: 5
+            }
+            enumerator: "DCI_P3"
+            scalar_value: {
+                int32_t: 6
+            }
+            enumerator: "SRGB"
+            scalar_value: {
+                int32_t: 7
+            }
+            enumerator: "ADOBE_RGB"
+            scalar_value: {
+                int32_t: 8
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::ColorTransform"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "IDENTITY"
+            scalar_value: {
+                int32_t: 0
+            }
+            enumerator: "ARBITRARY_MATRIX"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "VALUE_INVERSE"
+            scalar_value: {
+                int32_t: 2
+            }
+            enumerator: "GRAYSCALE"
+            scalar_value: {
+                int32_t: 3
+            }
+            enumerator: "CORRECT_PROTANOPIA"
+            scalar_value: {
+                int32_t: 4
+            }
+            enumerator: "CORRECT_DEUTERANOPIA"
+            scalar_value: {
+                int32_t: 5
+            }
+            enumerator: "CORRECT_TRITANOPIA"
+            scalar_value: {
+                int32_t: 6
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::common::V1_0::Hdr"
+        type: TYPE_ENUM
+        enum_value: {
+            scalar_type: "int32_t"
+
+            enumerator: "DOLBY_VISION"
+            scalar_value: {
+                int32_t: 1
+            }
+            enumerator: "HDR10"
+            scalar_value: {
+                int32_t: 2
+            }
+            enumerator: "HLG"
+            scalar_value: {
+                int32_t: 3
+            }
+        }
+    }
+
+    attribute: {
+        name: "::android::hardware::graphics::allocator::V2_0::IAllocatorClient::BufferDescriptorInfo"
+        type: TYPE_STRUCT
+        struct_value: {
+            name: "width"
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        struct_value: {
+            name: "height"
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        struct_value: {
+            name: "layerCount"
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        struct_value: {
+            name: "format"
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::common::V1_0::PixelFormat"
+        }
+        struct_value: {
+            name: "producerUsageMask"
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        struct_value: {
+            name: "consumerUsageMask"
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+    }
+
+    api: {
+        name: "createDescriptor"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::IAllocatorClient::BufferDescriptorInfo"
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "destroyDescriptor"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        callflow: {
+            exit: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "testAllocate"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint64_t"
+            }
+        }
+        callflow: {
+            next: "allocate"
+        }
+    }
+
+    api: {
+        name: "allocate"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint64_t"
+            }
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint64_t"
+            }
+        }
+        callflow: {
+            next: "exportHandle"
+        }
+    }
+
+    api: {
+        name: "free"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        callflow: {
+            exit: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "exportHandle"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_HANDLE
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        callflow: {
+            next: "free"
+        }
+    }
+
+}
diff --git a/graphics/allocator/2.0/vts/Android.mk b/graphics/allocator/2.0/vts/Android.mk
new file mode 100644
index 0000000..00fd344
--- /dev/null
+++ b/graphics/allocator/2.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/graphics/allocator/hidl/target/Android.mk
diff --git a/graphics/allocator/2.0/vts/functional/Android.bp b/graphics/allocator/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..194b228
--- /dev/null
+++ b/graphics/allocator/2.0/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+//
+// 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_test {
+    name: "graphics_allocator_hidl_hal_test",
+    gtest: true,
+    srcs: ["graphics_allocator_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.graphics.allocator@2.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage",
+    ],
+}
diff --git a/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp b/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp
new file mode 100644
index 0000000..a0443d6
--- /dev/null
+++ b/graphics/allocator/2.0/vts/functional/graphics_allocator_hidl_hal_test.cpp
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "graphics_allocator_hidl_hal_test"
+
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <gtest/gtest.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace allocator {
+namespace V2_0 {
+namespace tests {
+namespace {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+#define CHECK_FEATURE_OR_SKIP(FEATURE_NAME)                 \
+  do {                                                      \
+    if (!hasCapability(FEATURE_NAME)) {                     \
+      std::cout << "[  SKIPPED ] Feature " << #FEATURE_NAME \
+                << " not supported" << std::endl;           \
+      return;                                               \
+    }                                                       \
+  } while (0)
+
+class TempDescriptor {
+ public:
+  TempDescriptor(const sp<IAllocatorClient>& client,
+                 const IAllocatorClient::BufferDescriptorInfo& info)
+      : mClient(client), mError(Error::NO_RESOURCES) {
+    mClient->createDescriptor(
+        info, [&](const auto& tmpError, const auto& tmpDescriptor) {
+          mError = tmpError;
+          mDescriptor = tmpDescriptor;
+        });
+  }
+
+  ~TempDescriptor() {
+    if (mError == Error::NONE) {
+      mClient->destroyDescriptor(mDescriptor);
+    }
+  }
+
+  bool isValid() const { return (mError == Error::NONE); }
+
+  operator BufferDescriptor() const { return mDescriptor; }
+
+ private:
+  sp<IAllocatorClient> mClient;
+  Error mError;
+  BufferDescriptor mDescriptor;
+};
+
+class GraphicsAllocatorHidlTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    mAllocator = IAllocator::getService("gralloc");
+    ASSERT_NE(mAllocator, nullptr);
+
+    mAllocator->createClient([this](const auto& error, const auto& client) {
+      if (error == Error::NONE) {
+        mClient = client;
+      }
+    });
+    ASSERT_NE(mClient, nullptr);
+
+    initCapabilities();
+
+    mDummyDescriptorInfo.width = 64;
+    mDummyDescriptorInfo.height = 64;
+    mDummyDescriptorInfo.layerCount = 1;
+    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+    mDummyDescriptorInfo.producerUsageMask =
+        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
+    mDummyDescriptorInfo.consumerUsageMask =
+        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+  }
+
+  void TearDown() override {}
+
+  /**
+   * Initialize the set of supported capabilities.
+   */
+  void initCapabilities() {
+    mAllocator->getCapabilities([this](const auto& capabilities) {
+      std::vector<IAllocator::Capability> caps = capabilities;
+      mCapabilities.insert(caps.cbegin(), caps.cend());
+    });
+  }
+
+  /**
+   * Test whether a capability is supported.
+   */
+  bool hasCapability(IAllocator::Capability capability) const {
+    return (mCapabilities.count(capability) > 0);
+  }
+
+  sp<IAllocator> mAllocator;
+  sp<IAllocatorClient> mClient;
+  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
+
+ private:
+  std::unordered_set<IAllocator::Capability> mCapabilities;
+};
+
+TEST_F(GraphicsAllocatorHidlTest, GetCapabilities) {
+  auto ret = mAllocator->getCapabilities([](const auto& capabilities) {
+    std::vector<IAllocator::Capability> caps = capabilities;
+    for (auto cap : caps) {
+      EXPECT_NE(IAllocator::Capability::INVALID, cap);
+    }
+  });
+
+  ASSERT_TRUE(ret.isOk());
+}
+
+TEST_F(GraphicsAllocatorHidlTest, DumpDebugInfo) {
+  auto ret = mAllocator->dumpDebugInfo([](const auto&) {
+    // nothing to do
+  });
+
+  ASSERT_TRUE(ret.isOk());
+}
+
+TEST_F(GraphicsAllocatorHidlTest, CreateDestroyDescriptor) {
+  Error error;
+  BufferDescriptor descriptor;
+  auto ret = mClient->createDescriptor(
+      mDummyDescriptorInfo,
+      [&](const auto& tmpError, const auto& tmpDescriptor) {
+        error = tmpError;
+        descriptor = tmpDescriptor;
+      });
+
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_EQ(Error::NONE, error);
+
+  auto err_ret = mClient->destroyDescriptor(descriptor);
+  ASSERT_TRUE(err_ret.isOk());
+  ASSERT_EQ(Error::NONE, static_cast<Error>(err_ret));
+}
+
+/**
+ * Test testAllocate with a single buffer descriptor.
+ */
+TEST_F(GraphicsAllocatorHidlTest, TestAllocateBasic) {
+  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
+
+  TempDescriptor descriptor(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor.isValid());
+
+  hidl_vec<BufferDescriptor> descriptors;
+  descriptors.resize(1);
+  descriptors[0] = descriptor;
+
+  auto ret = mClient->testAllocate(descriptors);
+  ASSERT_TRUE(ret.isOk());
+
+  auto error = static_cast<Error>(ret);
+  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
+}
+
+/**
+ * Test testAllocate with two buffer descriptors.
+ */
+TEST_F(GraphicsAllocatorHidlTest, TestAllocateArray) {
+  CHECK_FEATURE_OR_SKIP(IAllocator::Capability::TEST_ALLOCATE);
+
+  TempDescriptor descriptor(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor.isValid());
+
+  hidl_vec<BufferDescriptor> descriptors;
+  descriptors.resize(2);
+  descriptors[0] = descriptor;
+  descriptors[1] = descriptor;
+
+  auto ret = mClient->testAllocate(descriptors);
+  ASSERT_TRUE(ret.isOk());
+
+  auto error = static_cast<Error>(ret);
+  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
+}
+
+/**
+ * Test allocate/free with a single buffer descriptor.
+ */
+TEST_F(GraphicsAllocatorHidlTest, AllocateFreeBasic) {
+  TempDescriptor descriptor(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor.isValid());
+
+  hidl_vec<BufferDescriptor> descriptors;
+  descriptors.resize(1);
+  descriptors[0] = descriptor;
+
+  Error error;
+  std::vector<Buffer> buffers;
+  auto ret = mClient->allocate(
+      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
+        error = tmpError;
+        buffers = tmpBuffers;
+      });
+
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
+  EXPECT_EQ(1u, buffers.size());
+
+  if (!buffers.empty()) {
+    auto err_ret = mClient->free(buffers[0]);
+    EXPECT_TRUE(err_ret.isOk());
+    EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
+  }
+}
+
+/**
+ * Test allocate/free with an array of buffer descriptors.
+ */
+TEST_F(GraphicsAllocatorHidlTest, AllocateFreeArray) {
+  TempDescriptor descriptor1(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor1.isValid());
+
+  TempDescriptor descriptor2(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor2.isValid());
+
+  hidl_vec<BufferDescriptor> descriptors;
+  descriptors.resize(3);
+  descriptors[0] = descriptor1;
+  descriptors[1] = descriptor1;
+  descriptors[2] = descriptor2;
+
+  Error error;
+  std::vector<Buffer> buffers;
+  auto ret = mClient->allocate(
+      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
+        error = tmpError;
+        buffers = tmpBuffers;
+      });
+
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
+  EXPECT_EQ(descriptors.size(), buffers.size());
+
+  for (auto buf : buffers) {
+    auto err_ret = mClient->free(buf);
+    EXPECT_TRUE(err_ret.isOk());
+    EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
+  }
+}
+
+TEST_F(GraphicsAllocatorHidlTest, ExportHandle) {
+  TempDescriptor descriptor(mClient, mDummyDescriptorInfo);
+  ASSERT_TRUE(descriptor.isValid());
+
+  hidl_vec<BufferDescriptor> descriptors;
+  descriptors.resize(1);
+  descriptors[0] = descriptor;
+
+  Error error;
+  std::vector<Buffer> buffers;
+  auto ret = mClient->allocate(
+      descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
+        error = tmpError;
+        buffers = tmpBuffers;
+      });
+
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(error == Error::NONE || error == Error::NOT_SHARED);
+  ASSERT_EQ(1u, buffers.size());
+
+  ret = mClient->exportHandle(
+      descriptors[0], buffers[0],
+      [&](const auto& tmpError, const auto&) { error = tmpError; });
+  EXPECT_TRUE(ret.isOk());
+  EXPECT_EQ(Error::NONE, error);
+
+  auto err_ret = mClient->free(buffers[0]);
+  EXPECT_TRUE(err_ret.isOk());
+  EXPECT_EQ(Error::NONE, static_cast<Error>(err_ret));
+}
+
+}  // namespace anonymous
+}  // namespace tests
+}  // namespace V2_0
+}  // namespace allocator
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+
+  return status;
+}
diff --git a/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/Android.mk b/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/Android.mk
new file mode 100644
index 0000000..2c1617f
--- /dev/null
+++ b/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalGraphicsAllocatorHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/graphics/allocator/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/AndroidTest.xml b/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..4ef2e95
--- /dev/null
+++ b/graphics/allocator/2.0/vts/functional/vts/testcases/hal/graphics/allocator/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Graphics Allocator HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalGraphicsAllocatorHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/graphics_allocator_hidl_hal_test/graphics_allocator_hidl_hal_test,
+            _64bit::DATA/nativetest64/graphics_allocator_hidl_hal_test/graphics_allocator_hidl_hal_test,
+	    " />
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/graphics/allocator/2.0/vts/types.vts b/graphics/allocator/2.0/vts/types.vts
new file mode 100644
index 0000000..2b7e47a
--- /dev/null
+++ b/graphics/allocator/2.0/vts/types.vts
@@ -0,0 +1,134 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "types"
+
+package: "android.hardware.graphics.allocator"
+
+
+attribute: {
+    name: "::android::hardware::graphics::allocator::V2_0::Error"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "BAD_DESCRIPTOR"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "BAD_BUFFER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "BAD_VALUE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "NOT_SHARED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NO_RESOURCES"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "UNDEFINED"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "UNSUPPORTED"
+        scalar_value: {
+            int32_t: 7
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::graphics::allocator::V2_0::ProducerUsage"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint64_t"
+
+        enumerator: "CPU_READ"
+        scalar_value: {
+            uint64_t: 2
+        }
+        enumerator: "CPU_READ_OFTEN"
+        scalar_value: {
+            uint64_t: 4
+        }
+        enumerator: "CPU_WRITE"
+        scalar_value: {
+            uint64_t: 32
+        }
+        enumerator: "CPU_WRITE_OFTEN"
+        scalar_value: {
+            uint64_t: 64
+        }
+        enumerator: "GPU_RENDER_TARGET"
+        scalar_value: {
+            uint64_t: 512
+        }
+        enumerator: "PROTECTED"
+        scalar_value: {
+            uint64_t: 16384
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint64_t: 131072
+        }
+        enumerator: "VIDEO_DECODER"
+        scalar_value: {
+            uint64_t: 4194304
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::graphics::allocator::V2_0::ConsumerUsage"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint64_t"
+
+        enumerator: "CPU_READ"
+        scalar_value: {
+            uint64_t: 2
+        }
+        enumerator: "CPU_READ_OFTEN"
+        scalar_value: {
+            uint64_t: 4
+        }
+        enumerator: "GPU_TEXTURE"
+        scalar_value: {
+            uint64_t: 256
+        }
+        enumerator: "HWCOMPOSER"
+        scalar_value: {
+            uint64_t: 2048
+        }
+        enumerator: "CLIENT_TARGET"
+        scalar_value: {
+            uint64_t: 4096
+        }
+        enumerator: "CURSOR"
+        scalar_value: {
+            uint64_t: 32768
+        }
+        enumerator: "VIDEO_ENCODER"
+        scalar_value: {
+            uint64_t: 65536
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint64_t: 262144
+        }
+        enumerator: "RENDERSCRIPT"
+        scalar_value: {
+            uint64_t: 1048576
+        }
+    }
+}
+
diff --git a/graphics/allocator/Android.mk b/graphics/allocator/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/graphics/allocator/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
new file mode 100644
index 0000000..b67afd1
--- /dev/null
+++ b/graphics/common/1.0/Android.bp
@@ -0,0 +1,46 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.graphics.common@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.common@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/common/1.0/types.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.common@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.common@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/graphics/common/1.0/types.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.common@1.0",
+    generated_sources: ["android.hardware.graphics.common@1.0_genc++"],
+    generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/graphics/common/1.0/Android.mk b/graphics/common/1.0/Android.mk
new file mode 100644
index 0000000..0fa6dcc
--- /dev/null
+++ b/graphics/common/1.0/Android.mk
@@ -0,0 +1,291 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.graphics.common@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (ColorMode)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.ColorMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ColorTransform)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorTransform.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.ColorTransform
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Dataspace)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Dataspace.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Dataspace
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Hdr)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Hdr.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Hdr
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PixelFormat)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/PixelFormat.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.PixelFormat
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Transform)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Transform.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Transform
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.graphics.common@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+#
+# Build types.hal (ColorMode)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.ColorMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ColorTransform)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/ColorTransform.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.ColorTransform
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Dataspace)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Dataspace.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Dataspace
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Hdr)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Hdr.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Hdr
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PixelFormat)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/PixelFormat.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.PixelFormat
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Transform)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Transform.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0::types.Transform
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.graphics.common@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/graphics/common/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.graphics.common@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/graphics/common/1.0/types.hal b/graphics/common/1.0/types.hal
new file mode 100644
index 0000000..6fddfaf
--- /dev/null
+++ b/graphics/common/1.0/types.hal
@@ -0,0 +1,1377 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.common@1.0;
+
+/**
+ * pixel format definitions
+ */
+@export(name="android_pixel_format_t", value_prefix="HAL_PIXEL_FORMAT_")
+enum PixelFormat : int32_t {
+    /*
+     * "linear" color pixel formats:
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     *
+     * The color space determines, for example, if the formats are linear or
+     * gamma-corrected; or whether any special operations are performed when
+     * reading or writing into a buffer in one of these formats.
+     */
+    RGBA_8888          = 1,
+    RGBX_8888          = 2,
+    RGB_888            = 3,
+    RGB_565            = 4,
+    BGRA_8888          = 5,
+
+    /*
+     * The following formats use a 16bit float per color component.
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    RGBA_FP16          = 0x16,
+
+    /*
+     * 0x101 - 0x1FF
+     *
+     * This range is reserved for pixel formats that are specific to the HAL
+     * implementation.  Implementations can use any value in this range to
+     * communicate video pixel formats between their HAL modules.  These formats
+     * must not have an alpha channel.  Additionally, an EGLimage created from a
+     * gralloc buffer of one of these formats must be supported for use with the
+     * GL_OES_EGL_image_external OpenGL ES extension.
+     */
+
+    /*
+     * Android YUV format:
+     *
+     * This format is exposed outside of the HAL to software decoders and
+     * applications.  EGLImageKHR must support it in conjunction with the
+     * OES_EGL_image_external extension.
+     *
+     * YV12 is a 4:2:0 YCrCb planar format comprised of a WxH Y plane followed
+     * by (W/2) x (H/2) Cr and Cb planes.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   y_size = stride * height
+     *   c_stride = ALIGN(stride/2, 16)
+     *   c_size = c_stride * height/2
+     *   size = y_size + c_size * 2
+     *   cr_offset = y_size
+     *   cb_offset = y_size + c_size
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    YV12   = 0x32315659, // YCrCb 4:2:0 Planar
+
+
+    /*
+     * Android Y8 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y8 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 8 bits.
+     *
+     * It is equivalent to just the Y plane from YV12.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     *
+     *   size = stride * height
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    Y8     = 0x20203859,
+
+    /*
+     * Android Y16 format:
+     *
+     * This format is exposed outside of the HAL to the framework.
+     * The expected gralloc usage flags are SW_* and HW_CAMERA_*,
+     * and no other HW_ flags will be used.
+     *
+     * Y16 is a YUV planar format comprised of a WxH Y plane,
+     * with each pixel being represented by 16 bits.
+     *
+     * It is just like Y8, but has double the bits per pixel (little endian).
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer, except that dataSpace field
+     * HAL_DATASPACE_DEPTH indicates that this buffer contains a depth
+     * image where each sample is a distance value measured by a depth camera,
+     * plus an associated confidence value.
+     */
+    Y16    = 0x20363159,
+
+    /*
+     * Android RAW sensor format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW16 is a single-channel, 16-bit, little endian format, typically
+     * representing raw Bayer-pattern images from an image sensor, with minimal
+     * processing.
+     *
+     * The exact pixel layout of the data in the buffer is sensor-dependent, and
+     * needs to be queried from the camera device.
+     *
+     * Generally, not all 16 bits are used; more common values are 10 or 12
+     * bits. If not all bits are used, the lower-order bits are filled first.
+     * All parameters to interpret the raw data (black and white points,
+     * color space, etc) must be queried from the camera device.
+     *
+     * This format assumes
+     * - an even width
+     * - an even height
+     * - a horizontal stride multiple of 16 pixels
+     * - a vertical stride equal to the height
+     * - strides are specified in pixels, not in bytes
+     *
+     *   size = stride * height * 2
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    RAW16 = 0x20,
+
+    /*
+     * Android RAW10 format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW10 is a single-channel, 10-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each 4 consecutive pixels are packed into 5 bytes (40 bits). Each one
+     * of the first 4 bytes contains the top 8 bits of each pixel, The fifth byte
+     * contains the 2 least significant bits of the 4 pixels, the exact layout data
+     * for each 4 consecutive pixels is illustrated below (Pi[j] stands for the jth
+     * bit of the ith pixel):
+     *
+     *          bit 7                                     bit 0
+     *          =====|=====|=====|=====|=====|=====|=====|=====|
+     * Byte 0: |P0[9]|P0[8]|P0[7]|P0[6]|P0[5]|P0[4]|P0[3]|P0[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 1: |P1[9]|P1[8]|P1[7]|P1[6]|P1[5]|P1[4]|P1[3]|P1[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 2: |P2[9]|P2[8]|P2[7]|P2[6]|P2[5]|P2[4]|P2[3]|P2[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 3: |P3[9]|P3[8]|P3[7]|P3[6]|P3[5]|P3[4]|P3[3]|P3[2]|
+     *         |-----|-----|-----|-----|-----|-----|-----|-----|
+     * Byte 4: |P3[1]|P3[0]|P2[1]|P2[0]|P1[1]|P1[0]|P0[1]|P0[0]|
+     *          ===============================================
+     *
+     * This format assumes
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (10 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (10 / 8), padding bytes will be present at the end of each
+     * row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    RAW10 = 0x25,
+
+    /*
+     * Android RAW12 format:
+     *
+     * This format is exposed outside of camera HAL to applications.
+     *
+     * RAW12 is a single-channel, 12-bit per pixel, densely packed in each row,
+     * unprocessed format, usually representing raw Bayer-pattern images coming from
+     * an image sensor.
+     *
+     * In an image buffer with this format, starting from the first pixel of each
+     * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+     * and second byte contains the top 8 bits of first and second pixel. The third
+     * byte contains the 4 least significant bits of the two pixels, the exact layout
+     * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+     * the jth bit of the ith pixel):
+     *
+     *           bit 7                                            bit 0
+     *          ======|======|======|======|======|======|======|======|
+     * Byte 0: |P0[11]|P0[10]|P0[ 9]|P0[ 8]|P0[ 7]|P0[ 6]|P0[ 5]|P0[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 1: |P1[11]|P1[10]|P1[ 9]|P1[ 8]|P1[ 7]|P1[ 6]|P1[ 5]|P1[ 4]|
+     *         |------|------|------|------|------|------|------|------|
+     * Byte 2: |P1[ 3]|P1[ 2]|P1[ 1]|P1[ 0]|P0[ 3]|P0[ 2]|P0[ 1]|P0[ 0]|
+     *          =======================================================
+     *
+     * This format assumes:
+     * - a width multiple of 4 pixels
+     * - an even height
+     * - a vertical stride equal to the height
+     * - strides are specified in bytes, not in pixels
+     *
+     *   size = stride * height
+     *
+     * When stride is equal to width * (12 / 8), there will be no padding bytes at
+     * the end of each row, the entire image data is densely packed. When stride is
+     * larger than width * (12 / 8), padding bytes will be present at the end of
+     * each row (including the last row).
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    RAW12 = 0x26,
+
+    /*
+     * Android opaque RAW format:
+     *
+     * This format is exposed outside of the camera HAL to applications.
+     *
+     * RAW_OPAQUE is a format for unprocessed raw image buffers coming from an
+     * image sensor. The actual structure of buffers of this format is
+     * implementation-dependent.
+     *
+     * This format must be accepted by the gralloc module when used with the
+     * following usage flags:
+     *    - GRALLOC_USAGE_HW_CAMERA_*
+     *    - GRALLOC_USAGE_SW_*
+     *    - GRALLOC_USAGE_RENDERSCRIPT
+     *
+     * When used with ANativeWindow, the dataSpace field should be
+     * HAL_DATASPACE_ARBITRARY, as raw image sensor buffers require substantial
+     * extra metadata to define.
+     */
+    RAW_OPAQUE = 0x24,
+
+    /*
+     * Android binary blob graphics buffer format:
+     *
+     * This format is used to carry task-specific data which does not have a
+     * standard image structure. The details of the format are left to the two
+     * endpoints.
+     *
+     * A typical use case is for transporting JPEG-compressed images from the
+     * Camera HAL to the framework or to applications.
+     *
+     * Buffers of this format must have a height of 1, and width equal to their
+     * size in bytes.
+     *
+     * When used with ANativeWindow, the mapping of the dataSpace field to
+     * buffer contents for BLOB is as follows:
+     *
+     *  dataSpace value               | Buffer contents
+     * -------------------------------+-----------------------------------------
+     *  HAL_DATASPACE_JFIF            | An encoded JPEG image
+     *  HAL_DATASPACE_DEPTH           | An android_depth_points buffer
+     *  Other                         | Unsupported
+     *
+     */
+    BLOB = 0x21,
+
+    /*
+     * Android format indicating that the choice of format is entirely up to the
+     * device-specific Gralloc implementation.
+     *
+     * The Gralloc implementation should examine the usage bits passed in when
+     * allocating a buffer with this format, and it should derive the pixel
+     * format from those usage flags.  This format will never be used with any
+     * of the GRALLOC_USAGE_SW_* usage flags.
+     *
+     * If a buffer of this format is to be used as an OpenGL ES texture, the
+     * framework will assume that sampling the texture will always return an
+     * alpha value of 1.0 (i.e. the buffer contains only opaque pixel values).
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    IMPLEMENTATION_DEFINED = 0x22,
+
+    /*
+     * Android flexible YCbCr 4:2:0 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:0
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * struct android_ycbcr (below) is the the struct used to describe it.
+     *
+     * This format must be accepted by the gralloc module when
+     * USAGE_SW_WRITE_* or USAGE_SW_READ_* are set.
+     *
+     * This format is locked for use by gralloc's (*lock_ycbcr) method, and
+     * locking with the (*lock) method will return an error.
+     *
+     * When used with ANativeWindow, the dataSpace field describes the color
+     * space of the buffer.
+     */
+    YCBCR_420_888 = 0x23,
+
+    /*
+     * Android flexible YCbCr 4:2:2 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:2:2
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    YCBCR_422_888 = 0x27,
+
+    /*
+     * Android flexible YCbCr 4:4:4 formats
+     *
+     * This format allows platforms to use an efficient YCbCr/YCrCb 4:4:4
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called YCbCr, it can be
+     * used to describe formats with either chromatic ordering, as well as
+     * whole planar or semiplanar layouts.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    YCBCR_444_888 = 0x28,
+
+    /*
+     * Android flexible RGB 888 formats
+     *
+     * This format allows platforms to use an efficient RGB/BGR/RGBX/BGRX
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGB, it can be
+     * used to describe formats with either color ordering and optional
+     * padding, as well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    FLEX_RGB_888 = 0x29,
+
+    /*
+     * Android flexible RGBA 8888 formats
+     *
+     * This format allows platforms to use an efficient RGBA/BGRA/ARGB/ABGR
+     * buffer layout, while still describing the general format in a
+     * layout-independent manner.  While called RGBA, it can be
+     * used to describe formats with any of the component orderings, as
+     * well as whole planar layout.
+     *
+     * This format is currently only used by SW readable buffers
+     * produced by MediaCodecs, so the gralloc module can ignore this format.
+     */
+    FLEX_RGBA_8888 = 0x2A,
+
+    /* Legacy formats (deprecated), used by ImageFormat.java */
+    YCBCR_422_SP       = 0x10,  // NV16
+    YCRCB_420_SP       = 0x11,  // NV21
+    YCBCR_422_I        = 0x14,  // YUY2
+    JPEG               = 0x100,
+};
+
+/**
+ * Transformation definitions
+ *
+ * IMPORTANT NOTE:
+ * ROT_90 is applied CLOCKWISE and AFTER FLIP_{H|V}.
+ *
+ */
+@export(name="android_transform_t", value_prefix="HAL_TRANSFORM_")
+enum Transform : int32_t {
+    /* flip source image horizontally (around the vertical axis) */
+    FLIP_H    = 0x01,
+    /* flip source image vertically (around the horizontal axis)*/
+    FLIP_V    = 0x02,
+    /* rotate source image 90 degrees clockwise */
+    ROT_90    = 0x04,
+    /* rotate source image 180 degrees */
+    ROT_180   = 0x03,
+    /* rotate source image 270 degrees clockwise */
+    ROT_270   = 0x07,
+
+    /* 0x08 is reserved */
+};
+
+/**
+ * Dataspace Definitions
+ * ======================
+ *
+ * Dataspace is the definition of how pixel values should be interpreted.
+ *
+ * For many formats, this is the colorspace of the image data, which includes
+ * primaries (including white point) and the transfer characteristic function,
+ * which describes both gamma curve and numeric range (within the bit depth).
+ *
+ * Other dataspaces include depth measurement data from a depth camera.
+ *
+ * A dataspace is comprised of a number of fields.
+ *
+ * Version
+ * --------
+ * The top 2 bits represent the revision of the field specification. This is
+ * currently always 0.
+ *
+ *
+ * bits    31-30 29                      -                          0
+ *        +-----+----------------------------------------------------+
+ * fields | Rev |            Revision specific fields                |
+ *        +-----+----------------------------------------------------+
+ *
+ * Field layout for version = 0:
+ * ----------------------------
+ *
+ * A dataspace is comprised of the following fields:
+ *      Standard
+ *      Transfer function
+ *      Range
+ *
+ * bits    31-30 29-27 26 -  22 21 -  16 15             -           0
+ *        +-----+-----+--------+--------+----------------------------+
+ * fields |  0  |Range|Transfer|Standard|    Legacy and custom       |
+ *        +-----+-----+--------+--------+----------------------------+
+ *          VV    RRR   TTTTT    SSSSSS    LLLLLLLL       LLLLLLLL
+ *
+ * If range, transfer and standard fields are all 0 (e.g. top 16 bits are
+ * all zeroes), the bottom 16 bits contain either a legacy dataspace value,
+ * or a custom value.
+ */
+@export(name="android_dataspace_t", value_prefix="HAL_DATASPACE_")
+enum Dataspace : int32_t {
+    /*
+     * Default-assumption data space, when not explicitly specified.
+     *
+     * It is safest to assume the buffer is an image with sRGB primaries and
+     * encoding ranges, but the consumer and/or the producer of the data may
+     * simply be using defaults. No automatic gamma transform should be
+     * expected, except for a possible display gamma transform when drawn to a
+     * screen.
+     */
+    UNKNOWN = 0x0,
+
+    /*
+     * Arbitrary dataspace with manually defined characteristics.  Definition
+     * for colorspaces or other meaning must be communicated separately.
+     *
+     * This is used when specifying primaries, transfer characteristics,
+     * etc. separately.
+     *
+     * A typical use case is in video encoding parameters (e.g. for H.264),
+     * where a colorspace can have separately defined primaries, transfer
+     * characteristics, etc.
+     */
+    ARBITRARY = 0x1,
+
+    /*
+     * Color-description aspects
+     *
+     * The following aspects define various characteristics of the color
+     * specification. These represent bitfields, so that a data space value
+     * can specify each of them independently.
+     */
+
+    STANDARD_SHIFT = 16,
+
+    /*
+     * Standard aspect
+     *
+     * Defines the chromaticity coordinates of the source primaries in terms of
+     * the CIE 1931 definition of x and y specified in ISO 11664-1.
+     */
+    STANDARD_MASK = 63 << STANDARD_SHIFT,  // 0x3F
+
+    /*
+     * Chromacity coordinates are unknown or are determined by the application.
+     * Implementations shall use the following suggested standards:
+     *
+     * All YCbCr formats: BT709 if size is 720p or larger (since most video
+     *                    content is letterboxed this corresponds to width is
+     *                    1280 or greater, or height is 720 or greater).
+     *                    BT601_625 if size is smaller than 720p or is JPEG.
+     * All RGB formats:   BT709.
+     *
+     * For all other formats standard is undefined, and implementations should use
+     * an appropriate standard for the data represented.
+     */
+    STANDARD_UNSPECIFIED = 0 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.300   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2126, KB = 0.0722 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT709 = 1 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     */
+    STANDARD_BT601_625 = 2 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.290   0.600
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT601_625_UNADJUSTED = 3 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+     *  for RGB conversion from the one purely determined by the primaries
+     *  to minimize the color shift into RGB space that uses BT.709
+     *  primaries.
+     */
+    STANDARD_BT601_525 = 4 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.310   0.595
+     *  blue            0.155   0.070
+     *  red             0.630   0.340
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+     * for RGB conversion (as in SMPTE 240M).
+     */
+    STANDARD_BT601_525_UNADJUSTED = 5 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT2020 = 6 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Use the unadjusted KR = 0.2627, KB = 0.0593 luminance interpretation
+     * for RGB conversion using the linear domain.
+     */
+    STANDARD_BT2020_CONSTANT_LUMINANCE = 7 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x      y
+     *  green           0.21   0.71
+     *  blue            0.14   0.08
+     *  red             0.67   0.33
+     *  white (C)       0.310  0.316
+     *
+     * Use the unadjusted KR = 0.30, KB = 0.11 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_BT470M = 8 << STANDARD_SHIFT,
+
+    /*
+     * Primaries:       x       y
+     *  green           0.243   0.692
+     *  blue            0.145   0.049
+     *  red             0.681   0.319
+     *  white (C)       0.310   0.316
+     *
+     * Use the unadjusted KR = 0.254, KB = 0.068 luminance interpretation
+     * for RGB conversion.
+     */
+    STANDARD_FILM = 9 << STANDARD_SHIFT,
+
+    /*
+     * SMPTE EG 432-1 and SMPTE RP 431-2. (DCI-P3)
+     * Primaries:       x       y
+     *  green           0.265   0.690
+     *  blue            0.150   0.060
+     *  red             0.680   0.320
+     *  white (D65)     0.3127  0.3290
+     */
+    STANDARD_DCI_P3 = 10 << STANDARD_SHIFT,
+
+    /*
+     * Adobe RGB
+     * Primaries:       x       y
+     *  green           0.210   0.710
+     *  blue            0.150   0.060
+     *  red             0.640   0.330
+     *  white (D65)     0.3127  0.3290
+     */
+    STANDARD_ADOBE_RGB = 11 << STANDARD_SHIFT,
+
+
+
+    TRANSFER_SHIFT = 22,
+
+    /*
+     * Transfer aspect
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     *
+     * For digital signals, E corresponds to the recorded value. Normally, the
+     * transfer function is applied in RGB space to each of the R, G and B
+     * components independently. This may result in color shift that can be
+     * minized by applying the transfer function in Lab space only for the L
+     * component. Implementation may apply the transfer function in RGB space
+     * for all pixel formats if desired.
+     */
+
+    TRANSFER_MASK = 31 << TRANSFER_SHIFT,  // 0x1F
+
+    /*
+     * Transfer characteristics are unknown or are determined by the
+     * application.
+     *
+     * Implementations should use the following transfer functions:
+     *
+     * For YCbCr formats: use TRANSFER_SMPTE_170M
+     * For RGB formats: use TRANSFER_SRGB
+     *
+     * For all other formats transfer function is undefined, and implementations
+     * should use an appropriate standard for the data represented.
+     */
+    TRANSFER_UNSPECIFIED = 0 << TRANSFER_SHIFT,
+
+    /*
+     * Transfer characteristic curve:
+     *  E = L
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_LINEAR = 1 << TRANSFER_SHIFT,
+
+    /*
+     * Transfer characteristic curve:
+     *
+     * E = 1.055 * L^(1/2.4) - 0.055  for 0.0031308 <= L <= 1
+     *   = 12.92 * L                  for 0 <= L < 0.0031308
+     *     L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *     E - corresponding electrical signal
+     */
+    TRANSFER_SRGB = 2 << TRANSFER_SHIFT,
+
+    /*
+     * BT.601 525, BT.601 625, BT.709, BT.2020
+     *
+     * Transfer characteristic curve:
+     *  E = 1.099 * L ^ 0.45 - 0.099  for 0.018 <= L <= 1
+     *    = 4.500 * L                 for 0 <= L < 0.018
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_SMPTE_170M = 3 << TRANSFER_SHIFT,
+
+    /*
+     * Assumed display gamma 2.2.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.2)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_2 = 4 << TRANSFER_SHIFT,
+
+    /*
+     *  display gamma 2.6.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.6)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_6 = 5 << TRANSFER_SHIFT,
+
+    /*
+     *  display gamma 2.8.
+     *
+     * Transfer characteristic curve:
+     *  E = L ^ (1/2.8)
+     *      L - luminance of image 0 <= L <= 1 for conventional colorimetry
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_GAMMA2_8 = 6 << TRANSFER_SHIFT,
+
+    /*
+     * SMPTE ST 2084
+     *
+     * Transfer characteristic curve:
+     *  E = ((c1 + c2 * L^n) / (1 + c3 * L^n)) ^ m
+     *  c1 = c3 - c2 + 1 = 3424 / 4096 = 0.8359375
+     *  c2 = 32 * 2413 / 4096 = 18.8515625
+     *  c3 = 32 * 2392 / 4096 = 18.6875
+     *  m = 128 * 2523 / 4096 = 78.84375
+     *  n = 0.25 * 2610 / 4096 = 0.1593017578125
+     *      L - luminance of image 0 <= L <= 1 for HDR colorimetry.
+     *          L = 1 corresponds to 10000 cd/m2
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_ST2084 = 7 << TRANSFER_SHIFT,
+
+    /*
+     * ARIB STD-B67 Hybrid Log Gamma
+     *
+     * Transfer characteristic curve:
+     *  E = r * L^0.5                 for 0 <= L <= 1
+     *    = a * ln(L - b) + c         for 1 < L
+     *  a = 0.17883277
+     *  b = 0.28466892
+     *  c = 0.55991073
+     *  r = 0.5
+     *      L - luminance of image 0 <= L for HDR colorimetry. L = 1 corresponds
+     *          to reference white level of 100 cd/m2
+     *      E - corresponding electrical signal
+     */
+    TRANSFER_HLG = 8 << TRANSFER_SHIFT,
+
+    RANGE_SHIFT = 27,
+
+    /*
+     * Range aspect
+     *
+     * Defines the range of values corresponding to the unit range of 0-1.
+     * This is defined for YCbCr only, but can be expanded to RGB space.
+     */
+    RANGE_MASK = 7 << RANGE_SHIFT,  // 0x7
+
+    /*
+     * Range is unknown or are determined by the application.  Implementations
+     * shall use the following suggested ranges:
+     *
+     * All YCbCr formats: limited range.
+     * All RGB or RGBA formats (including RAW and Bayer): full range.
+     * All Y formats: full range
+     *
+     * For all other formats range is undefined, and implementations should use
+     * an appropriate range for the data represented.
+     */
+    RANGE_UNSPECIFIED = 0 << RANGE_SHIFT,
+
+    /*
+     * Full range uses all values for Y, Cb and Cr from
+     * 0 to 2^b-1, where b is the bit depth of the color format.
+     */
+    RANGE_FULL = 1 << RANGE_SHIFT,
+
+    /*
+     * Limited range uses values 16/256*2^b to 235/256*2^b for Y, and
+     * 1/16*2^b to 15/16*2^b for Cb, Cr, R, G and B, where b is the bit depth of
+     * the color format.
+     *
+     * E.g. For 8-bit-depth formats:
+     * Luma (Y) samples should range from 16 to 235, inclusive
+     * Chroma (Cb, Cr) samples should range from 16 to 240, inclusive
+     *
+     * For 10-bit-depth formats:
+     * Luma (Y) samples should range from 64 to 940, inclusive
+     * Chroma (Cb, Cr) samples should range from 64 to 960, inclusive
+     */
+    RANGE_LIMITED = 2 << RANGE_SHIFT,
+
+    /*
+     * Extended range is used for scRGB. Intended for use with
+     * floating point pixel formats. [0.0 - 1.0] is the standard
+     * sRGB space. Values outside the range 0.0 - 1.0 can encode
+     * color outside the sRGB gamut.
+     * Used to blend / merge multiple dataspaces on a single display.
+     */
+    RANGE_EXTENDED = 3 << RANGE_SHIFT,
+
+    /*
+     * Legacy dataspaces
+     */
+
+    /*
+     * sRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in sRGB space, but
+     * are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are encoded using the full range ([0,255] for 8-bit) for all
+     * components.
+     */
+    SRGB_LINEAR = 0x200, // deprecated, use V0_SRGB_LINEAR
+
+    V0_SRGB_LINEAR = STANDARD_BT709 | TRANSFER_LINEAR | RANGE_FULL,
+
+
+    /*
+     * scRGB linear encoding:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    V0_SCRGB_LINEAR = STANDARD_BT709 | TRANSFER_LINEAR | RANGE_EXTENDED,
+
+
+    /*
+     * sRGB gamma encoding:
+     *
+     * The red, green and blue components are stored in sRGB space, and
+     * converted to linear space when read, using the SRGB transfer function
+     * for each of the R, G and B components. When written, the inverse
+     * transformation is performed.
+     *
+     * The alpha component, if present, is always stored in linear space and
+     * is left unmodified when read or written.
+     *
+     * Use full range and BT.709 standard.
+     */
+    SRGB = 0x201, // deprecated, use V0_SRGB
+
+    V0_SRGB = STANDARD_BT709 | TRANSFER_SRGB | RANGE_FULL,
+
+
+    /*
+     * scRGB:
+     *
+     * The red, green, and blue components are stored in extended sRGB space,
+     * but are linear, not gamma-encoded.
+     * The RGB primaries and the white point are the same as BT.709.
+     *
+     * The values are floating point.
+     * A pixel value of 1.0, 1.0, 1.0 corresponds to sRGB white (D65) at 80 nits.
+     * Values beyond the range [0.0 - 1.0] would correspond to other colors
+     * spaces and/or HDR content.
+     */
+    V0_SCRGB = STANDARD_BT709 | TRANSFER_SRGB | RANGE_EXTENDED,
+
+    /*
+     * YCbCr Colorspaces
+     * -----------------
+     *
+     * Primaries are given using (x,y) coordinates in the CIE 1931 definition
+     * of x and y specified by ISO 11664-1.
+     *
+     * Transfer characteristics are the opto-electronic transfer characteristic
+     * at the source as a function of linear optical intensity (luminance).
+     */
+
+    /*
+     * JPEG File Interchange Format (JFIF)
+     *
+     * Same model as BT.601-625, but all values (Y, Cb, Cr) range from 0 to 255
+     *
+     * Use full range, BT.601 transfer and BT.601_625 standard.
+     */
+    JFIF = 0x101, // deprecated, use V0_JFIF
+
+    V0_JFIF = STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_FULL,
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 625-line
+     *
+     * Standard-definition television, 625 Lines (PAL)
+     *
+     * Use limited range, BT.601 transfer and BT.601_625 standard.
+     */
+    BT601_625 = 0x102, // deprecated, use V0_BT601_625
+
+    V0_BT601_625 = STANDARD_BT601_625 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
+
+
+    /*
+     * ITU-R Recommendation 601 (BT.601) - 525-line
+     *
+     * Standard-definition television, 525 Lines (NTSC)
+     *
+     * Use limited range, BT.601 transfer and BT.601_525 standard.
+     */
+    BT601_525 = 0x103, // deprecated, use V0_BT601_525
+
+    V0_BT601_525 = STANDARD_BT601_525 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
+
+    /*
+     * ITU-R Recommendation 709 (BT.709)
+     *
+     * High-definition television
+     *
+     * Use limited range, BT.709 transfer and BT.709 standard.
+     */
+    BT709 = 0x104, // deprecated, use V0_BT709
+
+    V0_BT709 = STANDARD_BT709 | TRANSFER_SMPTE_170M | RANGE_LIMITED,
+
+
+    /*
+     * SMPTE EG 432-1 and SMPTE RP 431-2.
+     *
+     * Digital Cinema DCI-P3
+     *
+     * Use full range, linear transfer and D65 DCI-P3 standard
+     */
+    DCI_P3_LINEAR = STANDARD_DCI_P3 | TRANSFER_LINEAR | RANGE_FULL,
+
+
+    /*
+     * SMPTE EG 432-1 and SMPTE RP 431-2.
+     *
+     * Digital Cinema DCI-P3
+     *
+     * Use full range, gamma 2.6 transfer and D65 DCI-P3 standard
+     * Note: Application is responsible for gamma encoding the data as
+     * a 2.6 gamma encoding is not supported in HW.
+     */
+    DCI_P3 = STANDARD_DCI_P3 | TRANSFER_GAMMA2_6 | RANGE_FULL,
+
+
+    /*
+     * Display P3
+     *
+     * Display P3 uses same primaries and white-point as DCI-P3
+     * linear transfer function makes this the same as DCI_P3_LINEAR.
+     */
+    DISPLAY_P3_LINEAR = STANDARD_DCI_P3 | TRANSFER_LINEAR | RANGE_FULL,
+
+
+    /*
+     * Display P3
+     *
+     * Use same primaries and white-point as DCI-P3
+     * but sRGB transfer function.
+     */
+    DISPLAY_P3 = STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_FULL,
+
+
+    /*
+     * Adobe RGB
+     *
+     * Use full range, gamma 2.2 transfer and Adobe RGB primaries
+     * Note: Application is responsible for gamma encoding the data as
+     * a 2.2 gamma encoding is not supported in HW.
+     */
+    ADOBE_RGB = STANDARD_ADOBE_RGB | TRANSFER_GAMMA2_2 | RANGE_FULL,
+
+
+    /*
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, linear transfer and BT2020 standard
+     */
+    BT2020_LINEAR = STANDARD_BT2020 | TRANSFER_LINEAR | RANGE_FULL,
+
+
+    /*
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, BT.709 transfer and BT2020 standard
+     */
+    BT2020 = STANDARD_BT2020 | TRANSFER_SMPTE_170M | RANGE_FULL,
+
+
+    /*
+     * Data spaces for non-color formats
+     */
+
+    /*
+     * The buffer contains depth ranging measurements from a depth camera.
+     * This value is valid with formats:
+     *    HAL_PIXEL_FORMAT_Y16: 16-bit samples, consisting of a depth measurement
+     *       and an associated confidence value. The 3 MSBs of the sample make
+     *       up the confidence value, and the low 13 LSBs of the sample make up
+     *       the depth measurement.
+     *       For the confidence section, 0 means 100% confidence, 1 means 0%
+     *       confidence. The mapping to a linear float confidence value between
+     *       0.f and 1.f can be obtained with
+     *         float confidence = (((depthSample >> 13) - 1) & 0x7) / 7.0f;
+     *       The depth measurement can be extracted simply with
+     *         uint16_t range = (depthSample & 0x1FFF);
+     *    HAL_PIXEL_FORMAT_BLOB: A depth point cloud, as
+     *       a variable-length float (x,y,z, confidence) coordinate point list.
+     *       The point cloud will be represented with the android_depth_points
+     *       structure.
+     */
+    DEPTH = 0x1000
+};
+
+/*
+ * Color modes that may be supported by a display.
+ *
+ * Definitions:
+ * Rendering intent generally defines the goal in mapping a source (input)
+ * color to a destination device color for a given color mode.
+ *
+ *  It is important to keep in mind three cases where mapping may be applied:
+ *  1. The source gamut is much smaller than the destination (display) gamut
+ *  2. The source gamut is much larger than the destination gamut (this will
+ *  ordinarily be handled using colorimetric rendering, below)
+ *  3. The source and destination gamuts are roughly equal, although not
+ *  completely overlapping
+ *  Also, a common requirement for mappings is that skin tones should be
+ *  preserved, or at least remain natural in appearance.
+ *
+ *  Colorimetric Rendering Intent (All cases):
+ *  Colorimetric indicates that colors should be preserved. In the case
+ *  that the source gamut lies wholly within the destination gamut or is
+ *  about the same (#1, #3), this will simply mean that no manipulations
+ *  (no saturation boost, for example) are applied. In the case where some
+ *  source colors lie outside the destination gamut (#2, #3), those will
+ *  need to be mapped to colors that are within the destination gamut,
+ *  while the already in-gamut colors remain unchanged.
+ *
+ *  Non-colorimetric transforms can take many forms. There are no hard
+ *  rules and it's left to the implementation to define.
+ *  Two common intents are described below.
+ *
+ *  Stretched-Gamut Enhancement Intent (Source < Destination):
+ *  When the destination gamut is much larger than the source gamut (#1), the
+ *  source primaries may be redefined to reflect the full extent of the
+ *  destination space, or to reflect an intermediate gamut.
+ *  Skin-tone preservation would likely be applied. An example might be sRGB
+ *  input displayed on a DCI-P3 capable device, with skin-tone preservation.
+ *
+ *  Within-Gamut Enhancement Intent (Source >= Destination):
+ *  When the device (destination) gamut is not larger than the source gamut
+ *  (#2 or #3), but the appearance of a larger gamut is desired, techniques
+ *  such as saturation boost may be applied to the source colors. Skin-tone
+ *  preservation may be applied. There is no unique method for within-gamut
+ *  enhancement; it would be defined within a flexible color mode.
+ *
+ */
+@export(name="android_color_mode_t", value_prefix="HAL_COLOR_MODE_")
+enum ColorMode : int32_t {
+  /*
+   * DEFAULT is the "native" gamut of the display.
+   * White Point: Vendor/OEM defined
+   * Panel Gamma: Vendor/OEM defined (typically 2.2)
+   * Rendering Intent: Vendor/OEM defined (typically 'enhanced')
+   */
+  NATIVE = 0,
+
+  /*
+   * STANDARD_BT601_625 corresponds with display
+   * settings that implement the ITU-R Recommendation BT.601
+   * or Rec 601. Using 625 line version
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.290   0.600
+   *  blue            0.150   0.060
+   *  red             0.640   0.330
+   *  white (D65)     0.3127  0.3290
+   *
+   *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+   *  for RGB conversion from the one purely determined by the primaries
+   *  to minimize the color shift into RGB space that uses BT.709
+   *  primaries.
+   *
+   * Gamma Correction (GC):
+   *
+   *  if Vlinear < 0.018
+   *    Vnonlinear = 4.500 * Vlinear
+   *  else
+   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+   */
+  STANDARD_BT601_625 = 1,
+
+  /*
+   * Primaries:
+   *                  x       y
+   *  green           0.290   0.600
+   *  blue            0.150   0.060
+   *  red             0.640   0.330
+   *  white (D65)     0.3127  0.3290
+   *
+   *  Use the unadjusted KR = 0.222, KB = 0.071 luminance interpretation
+   *  for RGB conversion.
+   *
+   * Gamma Correction (GC):
+   *
+   *  if Vlinear < 0.018
+   *    Vnonlinear = 4.500 * Vlinear
+   *  else
+   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+   */
+  STANDARD_BT601_625_UNADJUSTED = 2,
+
+  /*
+   * Primaries:
+   *                  x       y
+   *  green           0.310   0.595
+   *  blue            0.155   0.070
+   *  red             0.630   0.340
+   *  white (D65)     0.3127  0.3290
+   *
+   *  KR = 0.299, KB = 0.114. This adjusts the luminance interpretation
+   *  for RGB conversion from the one purely determined by the primaries
+   *  to minimize the color shift into RGB space that uses BT.709
+   *  primaries.
+   *
+   * Gamma Correction (GC):
+   *
+   *  if Vlinear < 0.018
+   *    Vnonlinear = 4.500 * Vlinear
+   *  else
+   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+   */
+  STANDARD_BT601_525 = 3,
+
+  /*
+   * Primaries:
+   *                  x       y
+   *  green           0.310   0.595
+   *  blue            0.155   0.070
+   *  red             0.630   0.340
+   *  white (D65)     0.3127  0.3290
+   *
+   *  Use the unadjusted KR = 0.212, KB = 0.087 luminance interpretation
+   *  for RGB conversion (as in SMPTE 240M).
+   *
+   * Gamma Correction (GC):
+   *
+   *  if Vlinear < 0.018
+   *    Vnonlinear = 4.500 * Vlinear
+   *  else
+   *    Vnonlinear = 1.099 * (Vlinear)^(0.45) – 0.099
+   */
+  STANDARD_BT601_525_UNADJUSTED = 4,
+
+  /*
+   * REC709 corresponds with display settings that implement
+   * the ITU-R Recommendation BT.709 / Rec. 709 for high-definition television.
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.300   0.600
+   *  blue            0.150   0.060
+   *  red             0.640   0.330
+   *  white (D65)     0.3127  0.3290
+   *
+   * HDTV REC709 Inverse Gamma Correction (IGC): V represents normalized
+   * (with [0 to 1] range) value of R, G, or B.
+   *
+   *  if Vnonlinear < 0.081
+   *    Vlinear = Vnonlinear / 4.5
+   *  else
+   *    Vlinear = ((Vnonlinear + 0.099) / 1.099) ^ (1/0.45)
+   *
+   * HDTV REC709 Gamma Correction (GC):
+   *
+   *  if Vlinear < 0.018
+   *    Vnonlinear = 4.5 * Vlinear
+   *  else
+   *    Vnonlinear = 1.099 * (Vlinear) ^ 0.45 – 0.099
+   */
+  STANDARD_BT709 = 5,
+
+  /*
+   * DCI_P3 corresponds with display settings that implement
+   * SMPTE EG 432-1 and SMPTE RP 431-2
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.265   0.690
+   *  blue            0.150   0.060
+   *  red             0.680   0.320
+   *  white (D65)     0.3127  0.3290
+   *
+   * Gamma: 2.6
+   */
+  DCI_P3 = 6,
+
+  /*
+   * SRGB corresponds with display settings that implement
+   * the sRGB color space. Uses the same primaries as ITU-R Recommendation
+   * BT.709
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.300   0.600
+   *  blue            0.150   0.060
+   *  red             0.640   0.330
+   *  white (D65)     0.3127  0.3290
+   *
+   * PC/Internet (sRGB) Inverse Gamma Correction (IGC):
+   *
+   *  if Vnonlinear ≤ 0.03928
+   *    Vlinear = Vnonlinear / 12.92
+   *  else
+   *    Vlinear = ((Vnonlinear + 0.055)/1.055) ^ 2.4
+   *
+   * PC/Internet (sRGB) Gamma Correction (GC):
+   *
+   *  if Vlinear ≤ 0.0031308
+   *    Vnonlinear = 12.92 * Vlinear
+   *  else
+   *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+   */
+  SRGB = 7,
+
+  /*
+   * ADOBE_RGB corresponds with the RGB color space developed
+   * by Adobe Systems, Inc. in 1998.
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.210   0.710
+   *  blue            0.150   0.060
+   *  red             0.640   0.330
+   *  white (D65)     0.3127  0.3290
+   *
+   * Gamma: 2.2
+   */
+  ADOBE_RGB = 8,
+
+  /*
+   * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+   * the D65 white point and the SRGB transfer functions.
+   * Rendering Intent: Colorimetric
+   * Primaries:
+   *                  x       y
+   *  green           0.265   0.690
+   *  blue            0.150   0.060
+   *  red             0.680   0.320
+   *  white (D65)     0.3127  0.3290
+   *
+   * PC/Internet (sRGB) Gamma Correction (GC):
+   *
+   *  if Vlinear ≤ 0.0031308
+   *    Vnonlinear = 12.92 * Vlinear
+   *  else
+   *    Vnonlinear = 1.055 * (Vlinear)^(1/2.4) – 0.055
+   */
+  DISPLAY_P3 = 9
+};
+
+/*
+ * Color transforms that may be applied by hardware composer to the whole
+ * display.
+ */
+@export(name="android_color_transform_t", value_prefix="HAL_COLOR_TRANSFORM_")
+enum ColorTransform : int32_t {
+    /* Applies no transform to the output color */
+    IDENTITY = 0,
+
+    /* Applies an arbitrary transform defined by a 4x4 affine matrix */
+    ARBITRARY_MATRIX = 1,
+
+    /* Applies a transform that inverts the value or luminance of the color, but
+     * does not modify hue or saturation */
+    VALUE_INVERSE = 2,
+
+    /* Applies a transform that maps all colors to shades of gray */
+    GRAYSCALE = 3,
+
+    /* Applies a transform which corrects for protanopic color blindness */
+    CORRECT_PROTANOPIA = 4,
+
+    /* Applies a transform which corrects for deuteranopic color blindness */
+    CORRECT_DEUTERANOPIA = 5,
+
+    /* Applies a transform which corrects for tritanopic color blindness */
+    CORRECT_TRITANOPIA = 6
+};
+
+/*
+ * Supported HDR formats. Must be kept in sync with equivalents in Display.java.
+ */
+@export(name="android_hdr_t", value_prefix="HAL_HDR_")
+enum Hdr : int32_t {
+    /* Device supports Dolby Vision HDR */
+    DOLBY_VISION = 1,
+
+    /* Device supports HDR10 */
+    HDR10 = 2,
+
+    /* Device supports hybrid log-gamma HDR */
+    HLG = 3
+};
diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp
new file mode 100644
index 0000000..7216c0f
--- /dev/null
+++ b/graphics/composer/2.1/Android.bp
@@ -0,0 +1,74 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.graphics.composer@2.1_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.composer@2.1",
+    srcs: [
+        "types.hal",
+        "IComposer.hal",
+        "IComposerCallback.hal",
+        "IComposerClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/composer/2.1/types.cpp",
+        "android/hardware/graphics/composer/2.1/ComposerAll.cpp",
+        "android/hardware/graphics/composer/2.1/ComposerCallbackAll.cpp",
+        "android/hardware/graphics/composer/2.1/ComposerClientAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.composer@2.1_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.composer@2.1",
+    srcs: [
+        "types.hal",
+        "IComposer.hal",
+        "IComposerCallback.hal",
+        "IComposerClient.hal",
+    ],
+    out: [
+        "android/hardware/graphics/composer/2.1/types.h",
+        "android/hardware/graphics/composer/2.1/IComposer.h",
+        "android/hardware/graphics/composer/2.1/IHwComposer.h",
+        "android/hardware/graphics/composer/2.1/BnHwComposer.h",
+        "android/hardware/graphics/composer/2.1/BpHwComposer.h",
+        "android/hardware/graphics/composer/2.1/BsComposer.h",
+        "android/hardware/graphics/composer/2.1/IComposerCallback.h",
+        "android/hardware/graphics/composer/2.1/IHwComposerCallback.h",
+        "android/hardware/graphics/composer/2.1/BnHwComposerCallback.h",
+        "android/hardware/graphics/composer/2.1/BpHwComposerCallback.h",
+        "android/hardware/graphics/composer/2.1/BsComposerCallback.h",
+        "android/hardware/graphics/composer/2.1/IComposerClient.h",
+        "android/hardware/graphics/composer/2.1/IHwComposerClient.h",
+        "android/hardware/graphics/composer/2.1/BnHwComposerClient.h",
+        "android/hardware/graphics/composer/2.1/BpHwComposerClient.h",
+        "android/hardware/graphics/composer/2.1/BsComposerClient.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.composer@2.1",
+    generated_sources: ["android.hardware.graphics.composer@2.1_genc++"],
+    generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/graphics/composer/2.1/IComposer.hal b/graphics/composer/2.1/IComposer.hal
new file mode 100644
index 0000000..771fc7d
--- /dev/null
+++ b/graphics/composer/2.1/IComposer.hal
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.1;
+
+import IComposerClient;
+
+interface IComposer {
+    /*
+     * Optional capabilities which may be supported by some devices. The
+     * particular set of supported capabilities for a given device may be
+     * retrieved using getCapabilities.
+     */
+    enum Capability : int32_t {
+        INVALID = 0,
+
+        /*
+         * Specifies that the device supports sideband stream layers, for
+         * which buffer content updates and other synchronization will not be
+         * provided through the usual validate/present cycle and must be
+         * handled by an external implementation-defined mechanism. Only
+         * changes to layer state (such as position, size, etc.) need to be
+         * performed through the validate/present cycle.
+         */
+        SIDEBAND_STREAM = 1,
+
+        /*
+         * Specifies that the device will apply a color transform even when
+         * either the client or the device has chosen that all layers should
+         * be composed by the client. This will prevent the client from
+         * applying the color transform during its composition step.
+         */
+        SKIP_CLIENT_COLOR_TRANSFORM = 2,
+    };
+
+    /*
+     * Provides a list of supported capabilities (as described in the
+     * definition of Capability above). This list must not change after
+     * initialization.
+     *
+     * @return capabilities is a list of supported capabilities.
+     */
+    getCapabilities() generates (vec<Capability> capabilities);
+
+    /*
+     * Retrieves implementation-defined debug information, which will be
+     * displayed during, for example, `dumpsys SurfaceFlinger`.
+     *
+     * @return debugInfo is a string of debug information.
+     */
+    dumpDebugInfo() generates (string debugInfo);
+
+    /*
+     * Creates a client of the composer. All resources created by the client
+     * are owned by the client and are only visible to the client.
+     *
+     * There can only be one client at any time.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *         NO_RESOURCES when no more client can be created currently.
+     * @return client is the newly created client.
+     */
+    createClient() generates (Error error, IComposerClient client);
+};
diff --git a/graphics/composer/2.1/IComposerCallback.hal b/graphics/composer/2.1/IComposerCallback.hal
new file mode 100644
index 0000000..a8ca168
--- /dev/null
+++ b/graphics/composer/2.1/IComposerCallback.hal
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.1;
+
+interface IComposerCallback {
+    enum Connection : int32_t {
+        INVALID = 0,
+
+        /* The display has been connected */
+        CONNECTED = 1,
+        /* The display has been disconnected */
+        DISCONNECTED = 2,
+    };
+
+    /*
+     * Notifies the client that the given display has either been connected or
+     * disconnected. Every active display (even a built-in physical display)
+     * must trigger at least one hotplug notification, even if it only occurs
+     * immediately after callback registration.
+     *
+     * Displays which have been connected are assumed to be in PowerMode::OFF,
+     * and the onVsync callback should not be called for a display until vsync
+     * has been enabled with setVsyncEnabled.
+     *
+     * The client may call back into the device while the callback is in
+     * progress. The device must serialize calls to this callback such that
+     * only one thread is calling it at a time.
+     *
+     * @param display is the display that triggers the hotplug event.
+     * @param connected indicates whether the display is connected or
+     *        disconnected.
+     */
+    onHotplug(Display display, Connection connected);
+
+    /*
+     * Notifies the client to trigger a screen refresh. This forces all layer
+     * state for this display to be resent, and the display to be validated
+     * and presented, even if there have been no changes.
+
+     * This refresh will occur some time after the callback is initiated, but
+     * not necessarily before it returns.  It is safe to trigger this callback
+     * from other functions which call into the device.
+     *
+     * @param display is the display to refresh.
+     */
+    oneway onRefresh(Display display);
+
+    /*
+     * Notifies the client that a vsync event has occurred. This callback must
+     * only be triggered when vsync is enabled for this display (through
+     * setVsyncEnabled).
+     *
+     * @param display is the display which has received a vsync event
+     * @param timestamp is the CLOCK_MONOTONIC time at which the vsync event
+     *        occurred, in nanoseconds.
+     */
+    oneway onVsync(Display display, int64_t timestamp);
+};
diff --git a/graphics/composer/2.1/IComposerClient.hal b/graphics/composer/2.1/IComposerClient.hal
new file mode 100644
index 0000000..b0bd837
--- /dev/null
+++ b/graphics/composer/2.1/IComposerClient.hal
@@ -0,0 +1,1118 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.1;
+
+import android.hardware.graphics.common@1.0;
+import IComposerCallback;
+
+interface IComposerClient {
+    /* Display attributes queryable through getDisplayAttribute. */
+    enum Attribute : int32_t {
+        INVALID = 0,
+
+        /* Dimensions in pixels */
+        WIDTH = 1,
+        HEIGHT = 2,
+
+        /* Vsync period in nanoseconds */
+        VSYNC_PERIOD = 3,
+
+        /*
+         * Dots per thousand inches (DPI * 1000). Scaling by 1000 allows these
+         * numbers to be stored in an int32_t without losing too much
+         * precision. If the DPI for a configuration is unavailable or is
+         * considered unreliable, the device may return UNSUPPORTED instead.
+         */
+        DPI_X = 4,
+        DPI_Y = 5,
+    };
+
+    /* Display requests returned by getDisplayRequests. */
+    enum DisplayRequest : uint32_t {
+        /*
+         * Instructs the client to provide a new client target buffer, even if
+         * no layers are marked for client composition.
+         */
+        FLIP_CLIENT_TARGET = 1 << 0,
+
+        /*
+         * Instructs the client to write the result of client composition
+         * directly into the virtual display output buffer. If any of the
+         * layers are not marked as Composition::CLIENT or the given display
+         * is not a virtual display, this request has no effect.
+         */
+        WRITE_CLIENT_TARGET_TO_OUTPUT = 1 << 1,
+    };
+
+    /* Layer requests returned from getDisplayRequests. */
+    enum LayerRequest : uint32_t {
+        /*
+         * The client must clear its target with transparent pixels where
+         * this layer would be. The client may ignore this request if the
+         * layer must be blended.
+         */
+        CLEAR_CLIENT_TARGET = 1 << 0,
+    };
+
+    /* Power modes for use with setPowerMode. */
+    enum PowerMode : int32_t {
+        /* The display is fully off (blanked). */
+        OFF = 0,
+
+        /*
+         * These are optional low power modes. getDozeSupport may be called to
+         * determine whether a given display supports these modes.
+         */
+
+        /*
+         * The display is turned on and configured in a low power state that
+         * is suitable for presenting ambient information to the user,
+         * possibly with lower fidelity than ON, but with greater efficiency.
+         */
+        DOZE = 1,
+
+        /*
+         * The display is configured as in DOZE but may stop applying display
+         * updates from the client. This is effectively a hint to the device
+         * that drawing to the display has been suspended and that the the
+         * device must remain on in a low power state and continue
+         * displaying its current contents indefinitely until the power mode
+         * changes.
+         *
+         * This mode may also be used as a signal to enable hardware-based
+         * doze functionality. In this case, the device is free to take over
+         * the display and manage it autonomously to implement a low power
+         * always-on display.
+         */
+        DOZE_SUSPEND = 3,
+
+        /* The display is fully on. */
+        ON = 2,
+    };
+
+    /* Vsync values passed to setVsyncEnabled. */
+    enum Vsync : int32_t {
+        INVALID = 0,
+
+        /* Enable vsync. */
+        ENABLE = 1,
+
+        /* Disable vsync. */
+        DISABLE = 2,
+    };
+
+    /* Blend modes, settable per layer. */
+    enum BlendMode : int32_t {
+        INVALID = 0,
+
+        /* colorOut = colorSrc */
+        NONE = 1,
+
+        /* colorOut = colorSrc + colorDst * (1 - alphaSrc) */
+        PREMULTIPLIED = 2,
+
+        /* colorOut = colorSrc * alphaSrc + colorDst * (1 - alphaSrc) */
+        COVERAGE = 3,
+    };
+
+    /* Possible composition types for a given layer. */
+    enum Composition : int32_t {
+        INVALID = 0,
+
+        /*
+         * The client must composite this layer into the client target buffer
+         * (provided to the device through setClientTarget).
+         *
+         * The device must not request any composition type changes for layers
+         * of this type.
+         */
+        CLIENT = 1,
+
+        /*
+         * The device must handle the composition of this layer through a
+         * hardware overlay or other similar means.
+         *
+         * Upon validateDisplay, the device may request a change from this
+         * type to CLIENT.
+         */
+        DEVICE = 2,
+
+        /*
+         * The device must render this layer using the color set through
+         * setLayerColor. If this functionality is not supported on a layer
+         * that the client sets to SOLID_COLOR, the device must request that
+         * the composition type of that layer is changed to CLIENT upon the
+         * next call to validateDisplay.
+         *
+         * Upon validateDisplay, the device may request a change from this
+         * type to CLIENT.
+         */
+        SOLID_COLOR = 3,
+
+        /*
+         * Similar to DEVICE, but the position of this layer may also be set
+         * asynchronously through setCursorPosition. If this functionality is
+         * not supported on a layer that the client sets to CURSOR, the device
+         * must request that the composition type of that layer is changed to
+         * CLIENT upon the next call to validateDisplay.
+         *
+         * Upon validateDisplay, the device may request a change from this
+         * type to either DEVICE or CLIENT.  Changing to DEVICE will prevent
+         * the use of setCursorPosition but still permit the device to
+         * composite the layer.
+         */
+        CURSOR = 4,
+
+        /*
+         * The device must handle the composition of this layer, as well as
+         * its buffer updates and content synchronization. Only supported on
+         * devices which provide Capability::SIDEBAND_STREAM.
+         *
+         * Upon validateDisplay, the device may request a change from this
+         * type to either DEVICE or CLIENT, but it is unlikely that content
+         * will display correctly in these cases.
+         */
+        SIDEBAND = 5,
+    };
+
+    /* Display types returned by getDisplayType. */
+    enum DisplayType : int32_t {
+        INVALID = 0,
+
+        /*
+         * All physical displays, including both internal displays and
+         * hotpluggable external displays.
+         */
+        PHYSICAL = 1,
+
+        /* Virtual displays created by createVirtualDisplay. */
+        VIRTUAL = 2,
+    };
+
+    /* Special index values (always negative) for command queue commands. */
+    enum HandleIndex : int32_t {
+        /* No handle */
+        EMPTY = -1,
+
+        /* Use cached handle */
+        CACHED = -2,
+    };
+
+    struct Rect {
+        int32_t left;
+        int32_t top;
+        int32_t right;
+        int32_t bottom;
+    };
+
+    struct FRect {
+        float left;
+        float top;
+        float right;
+        float bottom;
+    };
+
+    struct Color {
+        uint8_t r;
+        uint8_t g;
+        uint8_t b;
+        uint8_t a;
+    };
+
+    /*
+     * Provides a IComposerCallback object for the device to call.
+     *
+     * This function must be called only once.
+     *
+     * @param callback is the IComposerCallback object.
+     */
+    registerCallback(IComposerCallback callback);
+
+    /*
+     * Returns the maximum number of virtual displays supported by this device
+     * (which may be 0). The client must not attempt to create more than this
+     * many virtual displays on this device. This number must not change for
+     * the lifetime of the device.
+     *
+     * @return count is the maximum number of virtual displays supported.
+     */
+    getMaxVirtualDisplayCount() generates (uint32_t count);
+
+    /*
+     * Creates a new virtual display with the given width and height. The
+     * format passed into this function is the default format requested by the
+     * consumer of the virtual display output buffers.
+     *
+     * The display must be assumed to be on from the time the first frame is
+     * presented until the display is destroyed.
+     *
+     * @param width is the width in pixels.
+     * @param height is the height in pixels.
+     * @param formatHint is the default output buffer format selected by
+     *        the consumer.
+     * @param outputBufferSlotCount is the number of output buffer slots to be
+     *        reserved.
+     * @return error is NONE upon success. Otherwise,
+     *         UNSUPPORTED when the width or height is too large for the
+     *                     device to be able to create a virtual display.
+     *         NO_RESOURCES when the device is unable to create a new virtual
+     *                      display at this time.
+     * @return display is the newly-created virtual display.
+     * @return format is the format of the buffer the device will produce.
+     */
+    createVirtualDisplay(uint32_t width,
+                         uint32_t height,
+                         PixelFormat formatHint,
+                         uint32_t outputBufferSlotCount)
+              generates (Error error,
+                         Display display,
+                         PixelFormat format);
+
+    /*
+     * Destroys a virtual display. After this call all resources consumed by
+     * this display may be freed by the device and any operations performed on
+     * this display must fail.
+     *
+     * @param display is the virtual display to destroy.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when the display handle which was passed in does
+     *                       not refer to a virtual display.
+     */
+    destroyVirtualDisplay(Display display) generates (Error error);
+
+    /*
+     * Creates a new layer on the given display.
+     *
+     * @param display is the display on which to create the layer.
+     * @param bufferSlotCount is the number of buffer slot to be reserved.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         NO_RESOURCES when the device was unable to create a layer this
+     *                      time.
+     * @return layer is the handle of the new layer.
+     */
+    createLayer(Display display,
+                uint32_t bufferSlotCount)
+     generates (Error error,
+                Layer layer);
+
+    /*
+     * Destroys the given layer.
+     *
+     * @param display is the display on which the layer was created.
+     * @param layer is the layer to destroy.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_LAYER when an invalid layer handle was passed in.
+     */
+    destroyLayer(Display display, Layer layer) generates (Error error);
+
+    /*
+     * Retrieves which display configuration is currently active.
+     *
+     * If no display configuration is currently active, this function must
+     * return BAD_CONFIG. It is the responsibility of the client to call
+     * setActiveConfig with a valid configuration before attempting to present
+     * anything on the display.
+     *
+     * @param display is the display to which the active config is queried.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_CONFIG when no configuration is currently active.
+     * @return config is the currently active display configuration.
+     */
+    getActiveConfig(Display display) generates (Error error, Config config);
+
+    /*
+     * Returns whether a client target with the given properties can be
+     * handled by the device.
+     *
+     * This function must return true for a client target with width and
+     * height equal to the active display configuration dimensions,
+     * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to
+     * return true for any other configuration.
+     *
+     * @param display is the display to query.
+     * @param width is the client target width in pixels.
+     * @param height is the client target height in pixels.
+     * @param format is the client target format.
+     * @param dataspace is the client target dataspace, as described in
+     *        setLayerDataspace.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         UNSUPPORTED when the given configuration is not supported.
+     */
+    getClientTargetSupport(Display display,
+                           uint32_t width,
+                           uint32_t height,
+                           PixelFormat format,
+                           Dataspace dataspace)
+                generates (Error error);
+
+    /*
+     * Returns the color modes supported on this display.
+     *
+     * All devices must support at least ColorMode::NATIVE.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return modes is an array of color modes.
+     */
+    getColorModes(Display display)
+       generates (Error error,
+                  vec<ColorMode> modes);
+
+    /*
+     * Returns a display attribute value for a particular display
+     * configuration.
+     *
+     * @param display is the display to query.
+     * @param config is the display configuration for which to return
+     *        attribute values.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_CONFIG when config does not name a valid configuration for
+     *                    this display.
+     *         BAD_PARAMETER when attribute is unrecognized.
+     *         UNSUPPORTED when attribute cannot be queried for the config.
+     * @return value is the value of the attribute.
+     */
+    getDisplayAttribute(Display display,
+                        Config config,
+                        Attribute attribute)
+             generates (Error error,
+                        int32_t value);
+
+    /*
+     * Returns handles for all of the valid display configurations on this
+     * display.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return configs is an array of configuration handles.
+     */
+    getDisplayConfigs(Display display)
+           generates (Error error,
+                      vec<Config> configs);
+
+    /*
+     * Returns a human-readable version of the display's name.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return name is the name of the display.
+     */
+    getDisplayName(Display display) generates (Error error, string name);
+
+    /*
+     * Returns whether the given display is a physical or virtual display.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return type is the type of the display.
+     */
+    getDisplayType(Display display) generates (Error error, DisplayType type);
+
+    /*
+     * Returns whether the given display supports PowerMode::DOZE and
+     * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit over
+     * DOZE (see the definition of PowerMode for more information), but if
+     * both DOZE and DOZE_SUSPEND are no different from PowerMode::ON, the
+     * device must not claim support.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return support is true only when the display supports doze modes.
+     */
+    getDozeSupport(Display display) generates (Error error, bool support);
+
+    /*
+     * Returns the high dynamic range (HDR) capabilities of the given display,
+     * which are invariant with regard to the active configuration.
+     *
+     * Displays which are not HDR-capable must return no types.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     * @return types is an array of HDR types, may have 0 elements if the
+     *         display is not HDR-capable.
+     * @return maxLuminance is the desired content maximum luminance for this
+     *         display in cd/m^2.
+     * @return maxAverageLuminance - the desired content maximum frame-average
+     *         luminance for this display in cd/m^2.
+     * @return minLuminance is the desired content minimum luminance for this
+     *         display in cd/m^2.
+     */
+    getHdrCapabilities(Display display)
+            generates (Error error,
+                       vec<Hdr> types,
+                       float maxLuminance,
+                       float maxAverageLuminance,
+                       float minLuminance);
+
+    /*
+     * Set the number of client target slots to be reserved.
+     *
+     * @param display is the display to which the slots are reserved.
+     * @param clientTargetSlotCount is the slot count for client targets.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         NO_RESOURCES when unable to reserve the slots.
+     */
+    setClientTargetSlotCount(Display display,
+                             uint32_t clientTargetSlotCount)
+                  generates (Error error);
+
+    /*
+     * Sets the active configuration for this display. Upon returning, the
+     * given display configuration must be active and remain so until either
+     * this function is called again or the display is disconnected.
+     *
+     * @param display is the display to which the active config is set.
+     * @param config is the new display configuration.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_CONFIG when the configuration handle passed in is not valid
+     *                    for this display.
+     */
+    setActiveConfig(Display display, Config config) generates (Error error);
+
+    /*
+     * Sets the color mode of the given display.
+     *
+     * Upon returning from this function, the color mode change must have
+     * fully taken effect.
+     *
+     * All devices must support at least ColorMode::NATIVE, and displays are
+     * assumed to be in this mode upon hotplug.
+     *
+     * @param display is the display to which the color mode is set.
+     * @param mode is the mode to set to.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when mode is not a valid color mode.
+     *         UNSUPPORTED when mode is not supported on this display.
+     */
+    setColorMode(Display display, ColorMode mode) generates (Error error);
+
+    /*
+     * Sets the power mode of the given display. The transition must be
+     * complete when this function returns. It is valid to call this function
+     * multiple times with the same power mode.
+     *
+     * All displays must support PowerMode::ON and PowerMode::OFF.  Whether a
+     * display supports PowerMode::DOZE or PowerMode::DOZE_SUSPEND may be
+     * queried using getDozeSupport.
+     *
+     * @param display is the display to which the power mode is set.
+     * @param mode is the new power mode.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when mode was not a valid power mode.
+     *         UNSUPPORTED when mode is not supported on this display.
+     */
+    setPowerMode(Display display, PowerMode mode) generates (Error error);
+
+    /*
+     * Enables or disables the vsync signal for the given display. Virtual
+     * displays never generate vsync callbacks, and any attempt to enable
+     * vsync for a virtual display though this function must succeed and have
+     * no other effect.
+     *
+     * @param display is the display to which the vsync mode is set.
+     * @param enabled indicates whether to enable or disable vsync
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_DISPLAY when an invalid display handle was passed in.
+     *         BAD_PARAMETER when enabled was an invalid value.
+     */
+    setVsyncEnabled(Display display, Vsync enabled) generates (Error error);
+
+    /*
+     * Sets the input command message queue.
+     *
+     * @param descriptor is the descriptor of the input command message queue.
+     * @return error is NONE upon success. Otherwise,
+     *         NO_RESOURCES when failed to set the queue temporarily.
+     */
+    setInputCommandQueue(fmq_sync<uint32_t> descriptor)
+              generates (Error error);
+
+    /*
+     * Gets the output command message queue.
+     *
+     * This function must only be called inside executeCommands closure.
+     *
+     * @return error is NONE upon success. Otherwise,
+     *         NO_RESOURCES when failed to get the queue temporarily.
+     * @return descriptor is the descriptor of the output command queue.
+     */
+    getOutputCommandQueue()
+              generates (Error error,
+                         fmq_sync<uint32_t> descriptor);
+
+    /*
+     * Executes commands from the input command message queue. Return values
+     * generated by the input commands are written to the output command
+     * message queue in the form of value commands.
+     *
+     * @param inLength is the length of input commands.
+     * @param inHandles is an array of handles referenced by the input
+     *        commands.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when inLength is not equal to the length of
+     *                       commands in the input command message queue.
+     *         NO_RESOURCES when the output command message queue was not
+     *                      properly drained.
+     * @param outQueueChanged indicates whether the output command message
+     *        queue has changed.
+     * @param outLength is the length of output commands.
+     * @param outHandles is an array of handles referenced by the output
+     *        commands.
+     */
+    executeCommands(uint32_t inLength,
+                    vec<handle> inHandles)
+         generates (Error error,
+                    bool outQueueChanged,
+                    uint32_t outLength,
+                    vec<handle> outHandles);
+
+    /*
+     * SELECT_DISPLAY has this pseudo prototype
+     *
+     *   selectDisplay(Display display);
+     *
+     * Selects the current display implied by all other commands.
+     *
+     * @param display is the newly selected display.
+     *
+     *
+     * SELECT_LAYER has this pseudo prototype
+     *
+     *   selectLayer(Layer layer);
+     *
+     * Selects the current layer implied by all implicit layer commands.
+     *
+     * @param layer is the newly selected layer.
+     *
+     *
+     * SET_ERROR has this pseudo prototype
+     *
+     *   setError(uint32_t location, Error error);
+     *
+     * Indicates an error generated by a command.
+     *
+     * @param location is the offset of the command in the input command
+     *        message queue.
+     * @param error is the error generated by the command.
+     *
+     *
+     * SET_CHANGED_COMPOSITION_TYPES has this pseudo prototype
+     *
+     *   setChangedCompositionTypes(vec<Layer> layers,
+     *                              vec<Composition> types);
+     *
+     * Sets the layers for which the device requires a different composition
+     * type than had been set prior to the last call to VALIDATE_DISPLAY. The
+     * client must either update its state with these types and call
+     * ACCEPT_DISPLAY_CHANGES, or must set new types and attempt to validate
+     * the display again.
+     *
+     * @param layers is an array of layer handles.
+     * @param types is an array of composition types, each corresponding to
+     *         an element of layers.
+     *
+     *
+     * SET_DISPLAY_REQUESTS has this pseudo prototype
+     *
+     *   setDisplayRequests(uint32_t displayRequestMask,
+     *                      vec<Layer> layers,
+     *                      vec<uint32_t> layerRequestMasks);
+     *
+     * Sets the display requests and the layer requests required for the last
+     * validated configuration.
+     *
+     * Display requests provide information about how the client must handle
+     * the client target. Layer requests provide information about how the
+     * client must handle an individual layer.
+     *
+     * @param displayRequestMask is the display requests for the current
+     *        validated state.
+     * @param layers is an array of layers which all have at least one
+     *        request.
+     * @param layerRequestMasks is the requests corresponding to each element
+     *        of layers.
+     *
+     *
+     * SET_PRESENT_FENCE has this pseudo prototype
+     *
+     *   setPresentFence(int32_t presentFenceIndex);
+     *
+     * Sets the present fence as a result of PRESENT_DISPLAY. For physical
+     * displays, this fence must be signaled at the vsync when the result
+     * of composition of this frame starts to appear (for video-mode panels)
+     * or starts to transfer to panel memory (for command-mode panels). For
+     * virtual displays, this fence must be signaled when writes to the output
+     * buffer have completed and it is safe to read from it.
+     *
+     * @param presentFenceIndex is an index into outHandles array.
+     *
+     *
+     * SET_RELEASE_FENCES has this pseudo prototype
+     *
+     *   setReleaseFences(vec<Layer> layers,
+     *                    vec<int32_t> releaseFenceIndices);
+     *
+     * Sets the release fences for device layers on this display which will
+     * receive new buffer contents this frame.
+     *
+     * A release fence is a file descriptor referring to a sync fence object
+     * which must be signaled after the device has finished reading from the
+     * buffer presented in the prior frame. This indicates that it is safe to
+     * start writing to the buffer again. If a given layer's fence is not
+     * returned from this function, it must be assumed that the buffer
+     * presented on the previous frame is ready to be written.
+     *
+     * The fences returned by this function must be unique for each layer
+     * (even if they point to the same underlying sync object).
+     *
+     * @param layers is an array of layer handles.
+     * @param releaseFenceIndices are indices into outHandles array, each
+     *        corresponding to an element of layers.
+     *
+     *
+     * SET_COLOR_TRANSFORM has this pseudo prototype
+     *
+     *   setColorTransform(float[16] matrix,
+     *                     ColorTransform hint);
+     *
+     * Sets a color transform which will be applied after composition.
+     *
+     * If hint is not ColorTransform::ARBITRARY, then the device may use the
+     * hint to apply the desired color transform instead of using the color
+     * matrix directly.
+     *
+     * If the device is not capable of either using the hint or the matrix to
+     * apply the desired color transform, it must force all layers to client
+     * composition during VALIDATE_DISPLAY.
+     *
+     * If IComposer::Capability::SKIP_CLIENT_COLOR_TRANSFORM is present, then
+     * the client must never apply the color transform during client
+     * composition, even if all layers are being composed by the client.
+     *
+     * The matrix provided is an affine color transformation of the following
+     * form:
+     *
+     * |r.r r.g r.b 0|
+     * |g.r g.g g.b 0|
+     * |b.r b.g b.b 0|
+     * |Tr  Tg  Tb  1|
+     *
+     * This matrix must be provided in row-major form:
+     *
+     * {r.r, r.g, r.b, 0, g.r, ...}.
+     *
+     * Given a matrix of this form and an input color [R_in, G_in, B_in], the
+     * output color [R_out, G_out, B_out] will be:
+     *
+     * R_out = R_in * r.r + G_in * g.r + B_in * b.r + Tr
+     * G_out = R_in * r.g + G_in * g.g + B_in * b.g + Tg
+     * B_out = R_in * r.b + G_in * g.b + B_in * b.b + Tb
+     *
+     * @param matrix is a 4x4 transform matrix (16 floats) as described above.
+     * @param hint is a hint value which may be used instead of the given
+     *        matrix unless it is ColorTransform::ARBITRARY.
+     *
+     *
+     * SET_CLIENT_TARGET has this pseudo prototype
+     *
+     *   setClientTarget(uint32_t targetSlot,
+     *                   int32_t targetIndex,
+     *                   int32_t acquireFenceIndex,
+     *                   Dataspace dataspace,
+     *                   vec<Rect> damage);
+     *
+     * Sets the buffer handle which will receive the output of client
+     * composition.  Layers marked as Composition::CLIENT must be composited
+     * into this buffer prior to the call to PRESENT_DISPLAY, and layers not
+     * marked as Composition::CLIENT must be composited with this buffer by
+     * the device.
+     *
+     * The buffer handle provided may be empty if no layers are being
+     * composited by the client. This must not result in an error (unless an
+     * invalid display handle is also provided).
+     *
+     * Also provides a file descriptor referring to an acquire sync fence
+     * object, which must be signaled when it is safe to read from the client
+     * target buffer.  If it is already safe to read from this buffer, an
+     * empty handle may be passed instead.
+     *
+     * For more about dataspaces, see SET_LAYER_DATASPACE.
+     *
+     * The damage parameter describes a surface damage region as defined in
+     * the description of SET_LAYER_SURFACE_DAMAGE.
+     *
+     * Will be called before PRESENT_DISPLAY if any of the layers are marked
+     * as Composition::CLIENT. If no layers are so marked, then it is not
+     * necessary to call this function. It is not necessary to call
+     * validateDisplay after changing the target through this function.
+     *
+     * @param targetSlot is the client target buffer slot to use.
+     * @param targetIndex is an index into inHandles for the new target
+     *        buffer.
+     * @param acquireFenceIndex is an index into inHandles for a sync fence
+     *        file descriptor as described above.
+     * @param dataspace is the dataspace of the buffer, as described in
+     *        setLayerDataspace.
+     * @param damage is the surface damage region.
+     *
+     *
+     * SET_OUTPUT_BUFFER has this pseudo prototype
+     *
+     *   setOutputBuffer(uint32_t bufferSlot,
+     *                   int32_t bufferIndex,
+     *                   int32_t releaseFenceIndex);
+     *
+     * Sets the output buffer for a virtual display. That is, the buffer to
+     * which the composition result will be written.
+     *
+     * Also provides a file descriptor referring to a release sync fence
+     * object, which must be signaled when it is safe to write to the output
+     * buffer. If it is already safe to write to the output buffer, an empty
+     * handle may be passed instead.
+     *
+     * Must be called at least once before PRESENT_DISPLAY, but does not have
+     * any interaction with layer state or display validation.
+     *
+     * @param bufferSlot is the new output buffer.
+     * @param bufferIndex is the new output buffer.
+     * @param releaseFenceIndex is a sync fence file descriptor as described
+     *        above.
+     *
+     *
+     * VALIDATE_DISPLAY has this pseudo prototype
+     *
+     *   validateDisplay();
+     *
+     * Instructs the device to inspect all of the layer state and determine if
+     * there are any composition type changes necessary before presenting the
+     * display. Permitted changes are described in the definition of
+     * Composition above.
+     *
+     *
+     * ACCEPT_DISPLAY_CHANGES has this pseudo prototype
+     *
+     *   acceptDisplayChanges();
+     *
+     * Accepts the changes required by the device from the previous
+     * validateDisplay call (which may be queried using
+     * getChangedCompositionTypes) and revalidates the display. This function
+     * is equivalent to requesting the changed types from
+     * getChangedCompositionTypes, setting those types on the corresponding
+     * layers, and then calling validateDisplay again.
+     *
+     * After this call it must be valid to present this display. Calling this
+     * after validateDisplay returns 0 changes must succeed with NONE, but
+     * must have no other effect.
+     *
+     *
+     * PRESENT_DISPLAY has this pseudo prototype
+     *
+     *   presentDisplay();
+     *
+     * Presents the current display contents on the screen (or in the case of
+     * virtual displays, into the output buffer).
+     *
+     * Prior to calling this function, the display must be successfully
+     * validated with validateDisplay. Note that setLayerBuffer and
+     * setLayerSurfaceDamage specifically do not count as layer state, so if
+     * there are no other changes to the layer state (or to the buffer's
+     * properties as described in setLayerBuffer), then it is safe to call
+     * this function without first validating the display.
+     *
+     *
+     * SET_LAYER_CURSOR_POSITION has this pseudo prototype
+     *
+     *   setLayerCursorPosition(int32_t x, int32_t y);
+     *
+     * Asynchronously sets the position of a cursor layer.
+     *
+     * Prior to validateDisplay, a layer may be marked as Composition::CURSOR.
+     * If validation succeeds (i.e., the device does not request a composition
+     * change for that layer), then once a buffer has been set for the layer
+     * and it has been presented, its position may be set by this function at
+     * any time between presentDisplay and any subsequent validateDisplay
+     * calls for this display.
+     *
+     * Once validateDisplay is called, this function must not be called again
+     * until the validate/present sequence is completed.
+     *
+     * May be called from any thread so long as it is not interleaved with the
+     * validate/present sequence as described above.
+     *
+     * @param layer is the layer to which the position is set.
+     * @param x is the new x coordinate (in pixels from the left of the
+     *        screen).
+     * @param y is the new y coordinate (in pixels from the top of the
+     *        screen).
+     *
+     *
+     * SET_LAYER_BUFFER has this pseudo prototype
+     *
+     *   setLayerBuffer(uint32_t bufferSlot,
+     *                  int32_t bufferIndex,
+     *                  int32_t acquireFenceIndex);
+     *
+     * Sets the buffer handle to be displayed for this layer. If the buffer
+     * properties set at allocation time (width, height, format, and usage)
+     * have not changed since the previous frame, it is not necessary to call
+     * validateDisplay before calling presentDisplay unless new state needs to
+     * be validated in the interim.
+     *
+     * Also provides a file descriptor referring to an acquire sync fence
+     * object, which must be signaled when it is safe to read from the given
+     * buffer. If it is already safe to read from the buffer, an empty handle
+     * may be passed instead.
+     *
+     * This function must return NONE and have no other effect if called for a
+     * layer with a composition type of Composition::SOLID_COLOR (because it
+     * has no buffer) or Composition::SIDEBAND or Composition::CLIENT (because
+     * synchronization and buffer updates for these layers are handled
+     * elsewhere).
+     *
+     * @param layer is the layer to which the buffer is set.
+     * @param bufferSlot is the buffer slot to use.
+     * @param bufferIndex is the buffer handle to set.
+     * @param acquireFenceIndex is a sync fence file descriptor as described above.
+     *
+     *
+     * SET_LAYER_SURFACE_DAMAGE has this pseudo prototype
+     *
+     *   setLayerSurfaceDamage(vec<Rect> damage);
+     *
+     * Provides the region of the source buffer which has been modified since
+     * the last frame. This region does not need to be validated before
+     * calling presentDisplay.
+     *
+     * Once set through this function, the damage region remains the same
+     * until a subsequent call to this function.
+     *
+     * If damage is non-empty, then it may be assumed that any portion of the
+     * source buffer not covered by one of the rects has not been modified
+     * this frame. If damage is empty, then the whole source buffer must be
+     * treated as if it has been modified.
+     *
+     * If the layer's contents are not modified relative to the prior frame,
+     * damage must contain exactly one empty rect([0, 0, 0, 0]).
+     *
+     * The damage rects are relative to the pre-transformed buffer, and their
+     * origin is the top-left corner. They must not exceed the dimensions of
+     * the latched buffer.
+     *
+     * @param layer is the layer to which the damage region is set.
+     * @param damage is the new surface damage region.
+     *
+     *
+     * SET_LAYER_BLEND_MODE has this pseudo prototype
+     *
+     *   setLayerBlendMode(BlendMode mode)
+     *
+     * Sets the blend mode of the given layer.
+     *
+     * @param mode is the new blend mode.
+     *
+     *
+     * SET_LAYER_COLOR has this pseudo prototype
+     *
+     *   setLayerColor(Color color);
+     *
+     * Sets the color of the given layer. If the composition type of the layer
+     * is not Composition::SOLID_COLOR, this call must succeed and have no
+     * other effect.
+     *
+     * @param color is the new color.
+     *
+     *
+     * SET_LAYER_COMPOSITION_TYPE has this pseudo prototype
+     *
+     *   setLayerCompositionType(Composition type);
+     *
+     * Sets the desired composition type of the given layer. During
+     * validateDisplay, the device may request changes to the composition
+     * types of any of the layers as described in the definition of
+     * Composition above.
+     *
+     * @param type is the new composition type.
+     *
+     *
+     * SET_LAYER_DATASPACE has this pseudo prototype
+     *
+     *   setLayerDataspace(Dataspace dataspace);
+     *
+     * Sets the dataspace that the current buffer on this layer is in.
+     *
+     * The dataspace provides more information about how to interpret the
+     * buffer contents, such as the encoding standard and color transform.
+     *
+     * See the values of Dataspace for more information.
+     *
+     * @param dataspace is the new dataspace.
+     *
+     *
+     * SET_LAYER_DISPLAY_FRAME has this pseudo prototype
+     *
+     *   setLayerDisplayFrame(Rect frame);
+     *
+     * Sets the display frame (the portion of the display covered by a layer)
+     * of the given layer. This frame must not exceed the display dimensions.
+     *
+     * @param frame is the new display frame.
+     *
+     *
+     * SET_LAYER_PLANE_ALPHA has this pseudo prototype
+     *
+     *   setLayerPlaneAlpha(float alpha);
+     *
+     * Sets an alpha value (a floating point value in the range [0.0, 1.0])
+     * which will be applied to the whole layer. It can be conceptualized as a
+     * preprocessing step which applies the following function:
+     *   if (blendMode == BlendMode::PREMULTIPLIED)
+     *       out.rgb = in.rgb * planeAlpha
+     *   out.a = in.a * planeAlpha
+     *
+     * If the device does not support this operation on a layer which is
+     * marked Composition::DEVICE, it must request a composition type change
+     * to Composition::CLIENT upon the next validateDisplay call.
+     *
+     * @param alpha is the plane alpha value to apply.
+     *
+     *
+     * SET_LAYER_SIDEBAND_STREAM has this pseudo prototype
+     *
+     *   setLayerSidebandStream(int32_t streamIndex)
+     *
+     * Sets the sideband stream for this layer. If the composition type of the
+     * given layer is not Composition::SIDEBAND, this call must succeed and
+     * have no other effect.
+     *
+     * @param streamIndex is the new sideband stream.
+     *
+     *
+     * SET_LAYER_SOURCE_CROP has this pseudo prototype
+     *
+     *   setLayerSourceCrop(FRect crop);
+     *
+     * Sets the source crop (the portion of the source buffer which will fill
+     * the display frame) of the given layer. This crop rectangle must not
+     * exceed the dimensions of the latched buffer.
+     *
+     * If the device is not capable of supporting a true float source crop
+     * (i.e., it will truncate or round the floats to integers), it must set
+     * this layer to Composition::CLIENT when crop is non-integral for the
+     * most accurate rendering.
+     *
+     * If the device cannot support float source crops, but still wants to
+     * handle the layer, it must use the following code (or similar) to
+     * convert to an integer crop:
+     *   intCrop.left = (int) ceilf(crop.left);
+     *   intCrop.top = (int) ceilf(crop.top);
+     *   intCrop.right = (int) floorf(crop.right);
+     *   intCrop.bottom = (int) floorf(crop.bottom);
+     *
+     * @param crop is the new source crop.
+     *
+     *
+     * SET_LAYER_TRANSFORM has this pseudo prototype
+     *
+     * Sets the transform (rotation/flip) of the given layer.
+     *
+     *   setLayerTransform(Transform transform);
+     *
+     * @param transform is the new transform.
+     *
+     *
+     * SET_LAYER_VISIBLE_REGION has this pseudo prototype
+     *
+     *   setLayerVisibleRegion(vec<Rect> visible);
+     *
+     * Specifies the portion of the layer that is visible, including portions
+     * under translucent areas of other layers. The region is in screen space,
+     * and must not exceed the dimensions of the screen.
+     *
+     * @param visible is the new visible region, in screen space.
+     *
+     *
+     * SET_LAYER_Z_ORDER has this pseudo prototype
+     *
+     *   setLayerZOrder(uint32_t z);
+     *
+     * Sets the desired Z order (height) of the given layer. A layer with a
+     * greater Z value occludes a layer with a lesser Z value.
+     *
+     * @param z is the new Z order.
+     */
+    enum Command : int32_t {
+        LENGTH_MASK                        = 0xffff,
+        OPCODE_SHIFT                       = 16,
+        OPCODE_MASK                        = 0xffff << OPCODE_SHIFT,
+
+        /* special commands */
+        SELECT_DISPLAY                     = 0x000 << OPCODE_SHIFT,
+        SELECT_LAYER                       = 0x001 << OPCODE_SHIFT,
+
+        /* value commands (for return values) */
+        SET_ERROR                          = 0x100 << OPCODE_SHIFT,
+        SET_CHANGED_COMPOSITION_TYPES      = 0x101 << OPCODE_SHIFT,
+        SET_DISPLAY_REQUESTS               = 0x102 << OPCODE_SHIFT,
+        SET_PRESENT_FENCE                  = 0x103 << OPCODE_SHIFT,
+        SET_RELEASE_FENCES                 = 0x104 << OPCODE_SHIFT,
+
+        /* display commands */
+        SET_COLOR_TRANSFORM                = 0x200 << OPCODE_SHIFT,
+        SET_CLIENT_TARGET                  = 0x201 << OPCODE_SHIFT,
+        SET_OUTPUT_BUFFER                  = 0x202 << OPCODE_SHIFT,
+        VALIDATE_DISPLAY                   = 0x203 << OPCODE_SHIFT,
+        ACCEPT_DISPLAY_CHANGES             = 0x204 << OPCODE_SHIFT,
+        PRESENT_DISPLAY                    = 0x205 << OPCODE_SHIFT,
+
+        /* layer commands (VALIDATE_DISPLAY not required) */
+        SET_LAYER_CURSOR_POSITION          = 0x300 << OPCODE_SHIFT,
+        SET_LAYER_BUFFER                   = 0x301 << OPCODE_SHIFT,
+        SET_LAYER_SURFACE_DAMAGE           = 0x302 << OPCODE_SHIFT,
+
+        /* layer state commands (VALIDATE_DISPLAY required) */
+        SET_LAYER_BLEND_MODE               = 0x400 << OPCODE_SHIFT,
+        SET_LAYER_COLOR                    = 0x401 << OPCODE_SHIFT,
+        SET_LAYER_COMPOSITION_TYPE         = 0x402 << OPCODE_SHIFT,
+        SET_LAYER_DATASPACE                = 0x403 << OPCODE_SHIFT,
+        SET_LAYER_DISPLAY_FRAME            = 0x404 << OPCODE_SHIFT,
+        SET_LAYER_PLANE_ALPHA              = 0x405 << OPCODE_SHIFT,
+        SET_LAYER_SIDEBAND_STREAM          = 0x406 << OPCODE_SHIFT,
+        SET_LAYER_SOURCE_CROP              = 0x407 << OPCODE_SHIFT,
+        SET_LAYER_TRANSFORM                = 0x408 << OPCODE_SHIFT,
+        SET_LAYER_VISIBLE_REGION           = 0x409 << OPCODE_SHIFT,
+        SET_LAYER_Z_ORDER                  = 0x40a << OPCODE_SHIFT,
+
+        /* 0x800 - 0xfff are reserved for vendor extensions */
+        /* 0x1000 - 0xffff are reserved */
+    };
+};
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
new file mode 100644
index 0000000..0d63c3c
--- /dev/null
+++ b/graphics/composer/2.1/default/Android.bp
@@ -0,0 +1,49 @@
+cc_library_shared {
+    name: "android.hardware.graphics.composer@2.1-impl",
+    relative_install_path: "hw",
+    srcs: ["Hwc.cpp", "HwcClient.cpp"],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "libbase",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.graphics.composer@2.1-service",
+    relative_install_path: "hw",
+    srcs: ["service.cpp", "Hwc.cpp", "HwcClient.cpp"],
+    cppflags: ["-DBINDERIZED"],
+    init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
+
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.composer@2.1",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libfmq",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libsync",
+        "libutils",
+    ],
+}
+
+cc_library_static {
+    name: "libhwcomposer-command-buffer",
+    shared_libs: ["android.hardware.graphics.composer@2.1"],
+    export_include_dirs: ["."],
+}
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
new file mode 100644
index 0000000..4efb12b
--- /dev/null
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -0,0 +1,711 @@
+/*
+ * 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 "HwcPassthrough"
+
+#include <type_traits>
+
+#include <log/log.h>
+
+#include "Hwc.h"
+#include "HwcClient.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace implementation {
+
+HwcHal::HwcHal(const hw_module_t* module)
+    : mDevice(nullptr), mDispatch()
+{
+    int status = hwc2_open(module, &mDevice);
+    if (status) {
+        LOG_ALWAYS_FATAL("failed to open hwcomposer2 device: %s",
+                strerror(-status));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+HwcHal::~HwcHal()
+{
+    hwc2_close(mDevice);
+}
+
+void HwcHal::initCapabilities()
+{
+    uint32_t count = 0;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<Capability> caps(count);
+    mDevice->getCapabilities(mDevice, &count, reinterpret_cast<
+              std::underlying_type<Capability>::type*>(caps.data()));
+    caps.resize(count);
+
+    mCapabilities.insert(caps.cbegin(), caps.cend());
+}
+
+template<typename T>
+void HwcHal::initDispatch(hwc2_function_descriptor_t desc, T* outPfn)
+{
+    auto pfn = mDevice->getFunction(mDevice, desc);
+    if (!pfn) {
+        LOG_ALWAYS_FATAL("failed to get hwcomposer2 function %d", desc);
+    }
+
+    *outPfn = reinterpret_cast<T>(pfn);
+}
+
+void HwcHal::initDispatch()
+{
+    initDispatch(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
+            &mDispatch.acceptDisplayChanges);
+    initDispatch(HWC2_FUNCTION_CREATE_LAYER, &mDispatch.createLayer);
+    initDispatch(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
+            &mDispatch.createVirtualDisplay);
+    initDispatch(HWC2_FUNCTION_DESTROY_LAYER, &mDispatch.destroyLayer);
+    initDispatch(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+            &mDispatch.destroyVirtualDisplay);
+    initDispatch(HWC2_FUNCTION_DUMP, &mDispatch.dump);
+    initDispatch(HWC2_FUNCTION_GET_ACTIVE_CONFIG, &mDispatch.getActiveConfig);
+    initDispatch(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+            &mDispatch.getChangedCompositionTypes);
+    initDispatch(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+            &mDispatch.getClientTargetSupport);
+    initDispatch(HWC2_FUNCTION_GET_COLOR_MODES, &mDispatch.getColorModes);
+    initDispatch(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
+            &mDispatch.getDisplayAttribute);
+    initDispatch(HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
+            &mDispatch.getDisplayConfigs);
+    initDispatch(HWC2_FUNCTION_GET_DISPLAY_NAME, &mDispatch.getDisplayName);
+    initDispatch(HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
+            &mDispatch.getDisplayRequests);
+    initDispatch(HWC2_FUNCTION_GET_DISPLAY_TYPE, &mDispatch.getDisplayType);
+    initDispatch(HWC2_FUNCTION_GET_DOZE_SUPPORT, &mDispatch.getDozeSupport);
+    initDispatch(HWC2_FUNCTION_GET_HDR_CAPABILITIES,
+            &mDispatch.getHdrCapabilities);
+    initDispatch(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+            &mDispatch.getMaxVirtualDisplayCount);
+    initDispatch(HWC2_FUNCTION_GET_RELEASE_FENCES,
+            &mDispatch.getReleaseFences);
+    initDispatch(HWC2_FUNCTION_PRESENT_DISPLAY, &mDispatch.presentDisplay);
+    initDispatch(HWC2_FUNCTION_REGISTER_CALLBACK,
+            &mDispatch.registerCallback);
+    initDispatch(HWC2_FUNCTION_SET_ACTIVE_CONFIG, &mDispatch.setActiveConfig);
+    initDispatch(HWC2_FUNCTION_SET_CLIENT_TARGET, &mDispatch.setClientTarget);
+    initDispatch(HWC2_FUNCTION_SET_COLOR_MODE, &mDispatch.setColorMode);
+    initDispatch(HWC2_FUNCTION_SET_COLOR_TRANSFORM,
+            &mDispatch.setColorTransform);
+    initDispatch(HWC2_FUNCTION_SET_CURSOR_POSITION,
+            &mDispatch.setCursorPosition);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
+            &mDispatch.setLayerBlendMode);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_BUFFER, &mDispatch.setLayerBuffer);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_COLOR, &mDispatch.setLayerColor);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+            &mDispatch.setLayerCompositionType);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_DATASPACE,
+            &mDispatch.setLayerDataspace);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
+            &mDispatch.setLayerDisplayFrame);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
+            &mDispatch.setLayerPlaneAlpha);
+
+    if (hasCapability(Capability::SIDEBAND_STREAM)) {
+        initDispatch(HWC2_FUNCTION_SET_LAYER_SIDEBAND_STREAM,
+                &mDispatch.setLayerSidebandStream);
+    }
+
+    initDispatch(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
+            &mDispatch.setLayerSourceCrop);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+            &mDispatch.setLayerSurfaceDamage);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_TRANSFORM,
+            &mDispatch.setLayerTransform);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+            &mDispatch.setLayerVisibleRegion);
+    initDispatch(HWC2_FUNCTION_SET_LAYER_Z_ORDER, &mDispatch.setLayerZOrder);
+    initDispatch(HWC2_FUNCTION_SET_OUTPUT_BUFFER, &mDispatch.setOutputBuffer);
+    initDispatch(HWC2_FUNCTION_SET_POWER_MODE, &mDispatch.setPowerMode);
+    initDispatch(HWC2_FUNCTION_SET_VSYNC_ENABLED, &mDispatch.setVsyncEnabled);
+    initDispatch(HWC2_FUNCTION_VALIDATE_DISPLAY, &mDispatch.validateDisplay);
+}
+
+bool HwcHal::hasCapability(Capability capability) const
+{
+    return (mCapabilities.count(capability) > 0);
+}
+
+Return<void> HwcHal::getCapabilities(getCapabilities_cb hidl_cb)
+{
+    std::vector<Capability> caps(
+            mCapabilities.cbegin(), mCapabilities.cend());
+
+    hidl_vec<Capability> caps_reply;
+    caps_reply.setToExternal(caps.data(), caps.size());
+    hidl_cb(caps_reply);
+
+    return Void();
+}
+
+Return<void> HwcHal::dumpDebugInfo(dumpDebugInfo_cb hidl_cb)
+{
+    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';
+
+    hidl_string buf_reply;
+    buf_reply.setToExternal(buf.data(), len);
+    hidl_cb(buf_reply);
+
+    return Void();
+}
+
+Return<void> HwcHal::createClient(createClient_cb hidl_cb)
+{
+    Error err = Error::NONE;
+    sp<HwcClient> client;
+
+    {
+        std::lock_guard<std::mutex> lock(mClientMutex);
+
+        // only one client is allowed
+        if (mClient == nullptr) {
+            client = new HwcClient(*this);
+            mClient = client;
+        } else {
+            err = Error::NO_RESOURCES;
+        }
+    }
+
+    hidl_cb(err, client);
+
+    return Void();
+}
+
+sp<HwcClient> HwcHal::getClient()
+{
+    std::lock_guard<std::mutex> lock(mClientMutex);
+    return (mClient != nullptr) ? mClient.promote() : nullptr;
+}
+
+void HwcHal::removeClient()
+{
+    std::lock_guard<std::mutex> lock(mClientMutex);
+    mClient = nullptr;
+}
+
+void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int32_t connected)
+{
+    auto hal = reinterpret_cast<HwcHal*>(callbackData);
+    auto client = hal->getClient();
+    if (client != nullptr) {
+        client->onHotplug(display,
+                static_cast<IComposerCallback::Connection>(connected));
+    }
+}
+
+void HwcHal::refreshHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display)
+{
+    auto hal = reinterpret_cast<HwcHal*>(callbackData);
+    auto client = hal->getClient();
+    if (client != nullptr) {
+        client->onRefresh(display);
+    }
+}
+
+void HwcHal::vsyncHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp)
+{
+    auto hal = reinterpret_cast<HwcHal*>(callbackData);
+    auto client = hal->getClient();
+    if (client != nullptr) {
+        client->onVsync(display, timestamp);
+    }
+}
+
+void HwcHal::enableCallback(bool enable)
+{
+    if (enable) {
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                reinterpret_cast<hwc2_function_pointer_t>(hotplugHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+                reinterpret_cast<hwc2_function_pointer_t>(refreshHook));
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+                reinterpret_cast<hwc2_function_pointer_t>(vsyncHook));
+    } else {
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
+                nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_REFRESH, this,
+                nullptr);
+        mDispatch.registerCallback(mDevice, HWC2_CALLBACK_VSYNC, this,
+                nullptr);
+    }
+}
+
+uint32_t HwcHal::getMaxVirtualDisplayCount()
+{
+    return mDispatch.getMaxVirtualDisplayCount(mDevice);
+}
+
+Error HwcHal::createVirtualDisplay(uint32_t width, uint32_t height,
+    PixelFormat* format, Display* outDisplay)
+{
+    int32_t hwc_format = static_cast<int32_t>(*format);
+    int32_t err = mDispatch.createVirtualDisplay(mDevice, width, height,
+            &hwc_format, outDisplay);
+    *format = static_cast<PixelFormat>(hwc_format);
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::destroyVirtualDisplay(Display display)
+{
+    int32_t err = mDispatch.destroyVirtualDisplay(mDevice, display);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::createLayer(Display display, Layer* outLayer)
+{
+    int32_t err = mDispatch.createLayer(mDevice, display, outLayer);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::destroyLayer(Display display, Layer layer)
+{
+    int32_t err = mDispatch.destroyLayer(mDevice, display, layer);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getActiveConfig(Display display, Config* outConfig)
+{
+    int32_t err = mDispatch.getActiveConfig(mDevice, display, outConfig);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getClientTargetSupport(Display display,
+        uint32_t width, uint32_t height,
+        PixelFormat format, Dataspace dataspace)
+{
+    int32_t err = mDispatch.getClientTargetSupport(mDevice, display,
+            width, height, static_cast<int32_t>(format),
+            static_cast<int32_t>(dataspace));
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getColorModes(Display display, hidl_vec<ColorMode>* outModes)
+{
+    uint32_t count = 0;
+    int32_t err = mDispatch.getColorModes(mDevice, display, &count, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    outModes->resize(count);
+    err = mDispatch.getColorModes(mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<ColorMode>::type*>(
+                outModes->data()));
+    if (err != HWC2_ERROR_NONE) {
+        *outModes = hidl_vec<ColorMode>();
+        return static_cast<Error>(err);
+    }
+
+    return Error::NONE;
+}
+
+Error HwcHal::getDisplayAttribute(Display display, Config config,
+        IComposerClient::Attribute attribute, int32_t* outValue)
+{
+    int32_t err = mDispatch.getDisplayAttribute(mDevice, display, config,
+            static_cast<int32_t>(attribute), outValue);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs)
+{
+    uint32_t count = 0;
+    int32_t err = mDispatch.getDisplayConfigs(mDevice, display,
+            &count, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    outConfigs->resize(count);
+    err = mDispatch.getDisplayConfigs(mDevice, display,
+            &count, outConfigs->data());
+    if (err != HWC2_ERROR_NONE) {
+        *outConfigs = hidl_vec<Config>();
+        return static_cast<Error>(err);
+    }
+
+    return Error::NONE;
+}
+
+Error HwcHal::getDisplayName(Display display, hidl_string* outName)
+{
+    uint32_t count = 0;
+    int32_t err = mDispatch.getDisplayName(mDevice, display, &count, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    std::vector<char> buf(count + 1);
+    err = mDispatch.getDisplayName(mDevice, display, &count, buf.data());
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+    buf.resize(count + 1);
+    buf[count] = '\0';
+
+    *outName = buf.data();
+
+    return Error::NONE;
+}
+
+Error HwcHal::getDisplayType(Display display,
+        IComposerClient::DisplayType* outType)
+{
+    int32_t hwc_type = HWC2_DISPLAY_TYPE_INVALID;
+    int32_t err = mDispatch.getDisplayType(mDevice, display, &hwc_type);
+    *outType = static_cast<IComposerClient::DisplayType>(hwc_type);
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getDozeSupport(Display display, bool* outSupport)
+{
+    int32_t hwc_support = 0;
+    int32_t err = mDispatch.getDozeSupport(mDevice, display, &hwc_support);
+    *outSupport = hwc_support;
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
+        float* outMaxLuminance, float* outMaxAverageLuminance,
+        float* outMinLuminance)
+{
+    uint32_t count = 0;
+    int32_t err = mDispatch.getHdrCapabilities(mDevice, display, &count,
+            nullptr, outMaxLuminance, outMaxAverageLuminance,
+            outMinLuminance);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    outTypes->resize(count);
+    err = mDispatch.getHdrCapabilities(mDevice, display, &count,
+            reinterpret_cast<std::underlying_type<Hdr>::type*>(
+                outTypes->data()), outMaxLuminance,
+            outMaxAverageLuminance, outMinLuminance);
+    if (err != HWC2_ERROR_NONE) {
+        *outTypes = hidl_vec<Hdr>();
+        return static_cast<Error>(err);
+    }
+
+    return Error::NONE;
+}
+
+Error HwcHal::setActiveConfig(Display display, Config config)
+{
+    int32_t err = mDispatch.setActiveConfig(mDevice, display, config);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setColorMode(Display display, ColorMode mode)
+{
+    int32_t err = mDispatch.setColorMode(mDevice, display,
+            static_cast<int32_t>(mode));
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setPowerMode(Display display, IComposerClient::PowerMode mode)
+{
+    int32_t err = mDispatch.setPowerMode(mDevice, display,
+            static_cast<int32_t>(mode));
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setVsyncEnabled(Display display, IComposerClient::Vsync enabled)
+{
+    int32_t err = mDispatch.setVsyncEnabled(mDevice, display,
+            static_cast<int32_t>(enabled));
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setColorTransform(Display display, const float* matrix,
+        int32_t hint)
+{
+    int32_t err = mDispatch.setColorTransform(mDevice, display, matrix, hint);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setClientTarget(Display display, buffer_handle_t target,
+        int32_t acquireFence, int32_t dataspace,
+        const std::vector<hwc_rect_t>& damage)
+{
+    hwc_region region = { damage.size(), damage.data() };
+    int32_t err = mDispatch.setClientTarget(mDevice, display, target,
+            acquireFence, dataspace, region);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setOutputBuffer(Display display, buffer_handle_t buffer,
+        int32_t releaseFence)
+{
+    int32_t err = mDispatch.setOutputBuffer(mDevice, display, buffer,
+            releaseFence);
+    // unlike in setClientTarget, releaseFence is owned by us
+    if (err == HWC2_ERROR_NONE && releaseFence >= 0) {
+        close(releaseFence);
+    }
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::validateDisplay(Display display,
+        std::vector<Layer>* outChangedLayers,
+        std::vector<IComposerClient::Composition>* outCompositionTypes,
+        uint32_t* outDisplayRequestMask,
+        std::vector<Layer>* outRequestedLayers,
+        std::vector<uint32_t>* outRequestMasks)
+{
+    uint32_t types_count = 0;
+    uint32_t reqs_count = 0;
+    int32_t err = mDispatch.validateDisplay(mDevice, display,
+            &types_count, &reqs_count);
+    if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
+        return static_cast<Error>(err);
+    }
+
+    err = mDispatch.getChangedCompositionTypes(mDevice, display,
+            &types_count, nullptr, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    outChangedLayers->resize(types_count);
+    outCompositionTypes->resize(types_count);
+    err = mDispatch.getChangedCompositionTypes(mDevice, display,
+            &types_count, outChangedLayers->data(),
+            reinterpret_cast<
+            std::underlying_type<IComposerClient::Composition>::type*>(
+                outCompositionTypes->data()));
+    if (err != HWC2_ERROR_NONE) {
+        outChangedLayers->clear();
+        outCompositionTypes->clear();
+        return static_cast<Error>(err);
+    }
+
+    int32_t display_reqs = 0;
+    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
+            &reqs_count, nullptr, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        outChangedLayers->clear();
+        outCompositionTypes->clear();
+        return static_cast<Error>(err);
+    }
+
+    outRequestedLayers->resize(reqs_count);
+    outRequestMasks->resize(reqs_count);
+    err = mDispatch.getDisplayRequests(mDevice, display, &display_reqs,
+            &reqs_count, outRequestedLayers->data(),
+            reinterpret_cast<int32_t*>(outRequestMasks->data()));
+    if (err != HWC2_ERROR_NONE) {
+        outChangedLayers->clear();
+        outCompositionTypes->clear();
+
+        outRequestedLayers->clear();
+        outRequestMasks->clear();
+        return static_cast<Error>(err);
+    }
+
+    *outDisplayRequestMask = display_reqs;
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::acceptDisplayChanges(Display display)
+{
+    int32_t err = mDispatch.acceptDisplayChanges(mDevice, display);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::presentDisplay(Display display, int32_t* outPresentFence,
+        std::vector<Layer>* outLayers, std::vector<int32_t>* outReleaseFences)
+{
+    *outPresentFence = -1;
+    int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
+    if (err != HWC2_ERROR_NONE) {
+        return static_cast<Error>(err);
+    }
+
+    uint32_t count = 0;
+    err = mDispatch.getReleaseFences(mDevice, display, &count,
+            nullptr, nullptr);
+    if (err != HWC2_ERROR_NONE) {
+        ALOGW("failed to get release fences");
+        return Error::NONE;
+    }
+
+    outLayers->resize(count);
+    outReleaseFences->resize(count);
+    err = mDispatch.getReleaseFences(mDevice, display, &count,
+            outLayers->data(), outReleaseFences->data());
+    if (err != HWC2_ERROR_NONE) {
+        ALOGW("failed to get release fences");
+        outLayers->clear();
+        outReleaseFences->clear();
+        return Error::NONE;
+    }
+
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerCursorPosition(Display display, Layer layer,
+        int32_t x, int32_t y)
+{
+    int32_t err = mDispatch.setCursorPosition(mDevice, display, layer, x, y);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerBuffer(Display display, Layer layer,
+        buffer_handle_t buffer, int32_t acquireFence)
+{
+    int32_t err = mDispatch.setLayerBuffer(mDevice, display, layer,
+            buffer, acquireFence);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerSurfaceDamage(Display display, Layer layer,
+        const std::vector<hwc_rect_t>& damage)
+{
+    hwc_region region = { damage.size(), damage.data() };
+    int32_t err = mDispatch.setLayerSurfaceDamage(mDevice, display, layer,
+            region);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerBlendMode(Display display, Layer layer, int32_t mode)
+{
+    int32_t err = mDispatch.setLayerBlendMode(mDevice, display, layer, mode);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerColor(Display display, Layer layer,
+        IComposerClient::Color color)
+{
+    hwc_color_t hwc_color{color.r, color.g, color.b, color.a};
+    int32_t err = mDispatch.setLayerColor(mDevice, display, layer, hwc_color);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerCompositionType(Display display, Layer layer,
+        int32_t type)
+{
+    int32_t err = mDispatch.setLayerCompositionType(mDevice, display, layer,
+            type);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerDataspace(Display display, Layer layer,
+        int32_t dataspace)
+{
+    int32_t err = mDispatch.setLayerDataspace(mDevice, display, layer,
+            dataspace);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerDisplayFrame(Display display, Layer layer,
+        const hwc_rect_t& frame)
+{
+    int32_t err = mDispatch.setLayerDisplayFrame(mDevice, display, layer,
+            frame);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerPlaneAlpha(Display display, Layer layer, float alpha)
+{
+    int32_t err = mDispatch.setLayerPlaneAlpha(mDevice, display, layer,
+            alpha);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerSidebandStream(Display display, Layer layer,
+        buffer_handle_t stream)
+{
+    int32_t err = mDispatch.setLayerSidebandStream(mDevice, display, layer,
+            stream);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerSourceCrop(Display display, Layer layer,
+        const hwc_frect_t& crop)
+{
+    int32_t err = mDispatch.setLayerSourceCrop(mDevice, display, layer, crop);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerTransform(Display display, Layer layer,
+        int32_t transform)
+{
+    int32_t err = mDispatch.setLayerTransform(mDevice, display, layer,
+            transform);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerVisibleRegion(Display display, Layer layer,
+        const std::vector<hwc_rect_t>& visible)
+{
+    hwc_region_t region = { visible.size(), visible.data() };
+    int32_t err = mDispatch.setLayerVisibleRegion(mDevice, display, layer,
+            region);
+    return static_cast<Error>(err);
+}
+
+Error HwcHal::setLayerZOrder(Display display, Layer layer, uint32_t z)
+{
+    int32_t err = mDispatch.setLayerZOrder(mDevice, display, layer, z);
+    return static_cast<Error>(err);
+}
+
+IComposer* HIDL_FETCH_IComposer(const char*)
+{
+    const hw_module_t* module = nullptr;
+    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &module);
+    if (err) {
+        ALOGE("failed to get hwcomposer module");
+        return nullptr;
+    }
+
+    return new HwcHal(module);
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
new file mode 100644
index 0000000..6420b31
--- /dev/null
+++ b/graphics/composer/2.1/default/Hwc.h
@@ -0,0 +1,211 @@
+/*
+ * 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_COMPOSER_V2_1_HWC_H
+#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
+
+#include <mutex>
+#include <unordered_set>
+#include <vector>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <hardware/hwcomposer2.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace implementation {
+
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Hdr;
+
+class HwcClient;
+
+class HwcHal : public IComposer {
+public:
+    HwcHal(const hw_module_t* module);
+    virtual ~HwcHal();
+
+    // IComposer interface
+    Return<void> getCapabilities(getCapabilities_cb hidl_cb) override;
+    Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override;
+    Return<void> createClient(createClient_cb hidl_cb) override;
+
+    bool hasCapability(Capability capability) const;
+
+    void removeClient();
+
+    void enableCallback(bool enable);
+
+    uint32_t getMaxVirtualDisplayCount();
+    Error createVirtualDisplay(uint32_t width, uint32_t height,
+        PixelFormat* format, Display* outDisplay);
+    Error destroyVirtualDisplay(Display display);
+
+    Error createLayer(Display display, Layer* outLayer);
+    Error destroyLayer(Display display, Layer layer);
+
+    Error getActiveConfig(Display display, Config* outConfig);
+    Error getClientTargetSupport(Display display,
+            uint32_t width, uint32_t height,
+            PixelFormat format, Dataspace dataspace);
+    Error getColorModes(Display display, hidl_vec<ColorMode>* outModes);
+    Error getDisplayAttribute(Display display, Config config,
+            IComposerClient::Attribute attribute, int32_t* outValue);
+    Error getDisplayConfigs(Display display, hidl_vec<Config>* outConfigs);
+    Error getDisplayName(Display display, hidl_string* outName);
+    Error getDisplayType(Display display,
+            IComposerClient::DisplayType* outType);
+    Error getDozeSupport(Display display, bool* outSupport);
+    Error getHdrCapabilities(Display display, hidl_vec<Hdr>* outTypes,
+            float* outMaxLuminance, float* outMaxAverageLuminance,
+            float* outMinLuminance);
+
+    Error setActiveConfig(Display display, Config config);
+    Error setColorMode(Display display, ColorMode mode);
+    Error setPowerMode(Display display, IComposerClient::PowerMode mode);
+    Error setVsyncEnabled(Display display, IComposerClient::Vsync enabled);
+
+    Error setColorTransform(Display display, const float* matrix,
+            int32_t hint);
+    Error setClientTarget(Display display, buffer_handle_t target,
+            int32_t acquireFence, int32_t dataspace,
+            const std::vector<hwc_rect_t>& damage);
+    Error setOutputBuffer(Display display, buffer_handle_t buffer,
+            int32_t releaseFence);
+    Error validateDisplay(Display display,
+            std::vector<Layer>* outChangedLayers,
+            std::vector<IComposerClient::Composition>* outCompositionTypes,
+            uint32_t* outDisplayRequestMask,
+            std::vector<Layer>* outRequestedLayers,
+            std::vector<uint32_t>* outRequestMasks);
+    Error acceptDisplayChanges(Display display);
+    Error presentDisplay(Display display, int32_t* outPresentFence,
+            std::vector<Layer>* outLayers,
+            std::vector<int32_t>* outReleaseFences);
+
+    Error setLayerCursorPosition(Display display, Layer layer,
+            int32_t x, int32_t y);
+    Error setLayerBuffer(Display display, Layer layer,
+            buffer_handle_t buffer, int32_t acquireFence);
+    Error setLayerSurfaceDamage(Display display, Layer layer,
+            const std::vector<hwc_rect_t>& damage);
+    Error setLayerBlendMode(Display display, Layer layer, int32_t mode);
+    Error setLayerColor(Display display, Layer layer,
+            IComposerClient::Color color);
+    Error setLayerCompositionType(Display display, Layer layer,
+            int32_t type);
+    Error setLayerDataspace(Display display, Layer layer,
+            int32_t dataspace);
+    Error setLayerDisplayFrame(Display display, Layer layer,
+            const hwc_rect_t& frame);
+    Error setLayerPlaneAlpha(Display display, Layer layer, float alpha);
+    Error setLayerSidebandStream(Display display, Layer layer,
+            buffer_handle_t stream);
+    Error setLayerSourceCrop(Display display, Layer layer,
+            const hwc_frect_t& crop);
+    Error setLayerTransform(Display display, Layer layer,
+            int32_t transform);
+    Error setLayerVisibleRegion(Display display, Layer layer,
+            const std::vector<hwc_rect_t>& visible);
+    Error setLayerZOrder(Display display, Layer layer, uint32_t z);
+
+private:
+    void initCapabilities();
+
+    template<typename T>
+    void initDispatch(hwc2_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    sp<HwcClient> getClient();
+
+    static void hotplugHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int32_t connected);
+    static void refreshHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display);
+    static void vsyncHook(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp);
+
+    hwc2_device_t* mDevice;
+
+    std::unordered_set<Capability> mCapabilities;
+
+    struct {
+        HWC2_PFN_ACCEPT_DISPLAY_CHANGES acceptDisplayChanges;
+        HWC2_PFN_CREATE_LAYER createLayer;
+        HWC2_PFN_CREATE_VIRTUAL_DISPLAY createVirtualDisplay;
+        HWC2_PFN_DESTROY_LAYER destroyLayer;
+        HWC2_PFN_DESTROY_VIRTUAL_DISPLAY destroyVirtualDisplay;
+        HWC2_PFN_DUMP dump;
+        HWC2_PFN_GET_ACTIVE_CONFIG getActiveConfig;
+        HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES getChangedCompositionTypes;
+        HWC2_PFN_GET_CLIENT_TARGET_SUPPORT getClientTargetSupport;
+        HWC2_PFN_GET_COLOR_MODES getColorModes;
+        HWC2_PFN_GET_DISPLAY_ATTRIBUTE getDisplayAttribute;
+        HWC2_PFN_GET_DISPLAY_CONFIGS getDisplayConfigs;
+        HWC2_PFN_GET_DISPLAY_NAME getDisplayName;
+        HWC2_PFN_GET_DISPLAY_REQUESTS getDisplayRequests;
+        HWC2_PFN_GET_DISPLAY_TYPE getDisplayType;
+        HWC2_PFN_GET_DOZE_SUPPORT getDozeSupport;
+        HWC2_PFN_GET_HDR_CAPABILITIES getHdrCapabilities;
+        HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT getMaxVirtualDisplayCount;
+        HWC2_PFN_GET_RELEASE_FENCES getReleaseFences;
+        HWC2_PFN_PRESENT_DISPLAY presentDisplay;
+        HWC2_PFN_REGISTER_CALLBACK registerCallback;
+        HWC2_PFN_SET_ACTIVE_CONFIG setActiveConfig;
+        HWC2_PFN_SET_CLIENT_TARGET setClientTarget;
+        HWC2_PFN_SET_COLOR_MODE setColorMode;
+        HWC2_PFN_SET_COLOR_TRANSFORM setColorTransform;
+        HWC2_PFN_SET_CURSOR_POSITION setCursorPosition;
+        HWC2_PFN_SET_LAYER_BLEND_MODE setLayerBlendMode;
+        HWC2_PFN_SET_LAYER_BUFFER setLayerBuffer;
+        HWC2_PFN_SET_LAYER_COLOR setLayerColor;
+        HWC2_PFN_SET_LAYER_COMPOSITION_TYPE setLayerCompositionType;
+        HWC2_PFN_SET_LAYER_DATASPACE setLayerDataspace;
+        HWC2_PFN_SET_LAYER_DISPLAY_FRAME setLayerDisplayFrame;
+        HWC2_PFN_SET_LAYER_PLANE_ALPHA setLayerPlaneAlpha;
+        HWC2_PFN_SET_LAYER_SIDEBAND_STREAM setLayerSidebandStream;
+        HWC2_PFN_SET_LAYER_SOURCE_CROP setLayerSourceCrop;
+        HWC2_PFN_SET_LAYER_SURFACE_DAMAGE setLayerSurfaceDamage;
+        HWC2_PFN_SET_LAYER_TRANSFORM setLayerTransform;
+        HWC2_PFN_SET_LAYER_VISIBLE_REGION setLayerVisibleRegion;
+        HWC2_PFN_SET_LAYER_Z_ORDER setLayerZOrder;
+        HWC2_PFN_SET_OUTPUT_BUFFER setOutputBuffer;
+        HWC2_PFN_SET_POWER_MODE setPowerMode;
+        HWC2_PFN_SET_VSYNC_ENABLED setVsyncEnabled;
+        HWC2_PFN_VALIDATE_DISPLAY validateDisplay;
+    } mDispatch;
+
+    std::mutex mClientMutex;
+    wp<HwcClient> mClient;
+};
+
+extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
diff --git a/graphics/composer/2.1/default/HwcClient.cpp b/graphics/composer/2.1/default/HwcClient.cpp
new file mode 100644
index 0000000..edd161a
--- /dev/null
+++ b/graphics/composer/2.1/default/HwcClient.cpp
@@ -0,0 +1,1128 @@
+/*
+ * 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 "HwcPassthrough"
+
+#include <hardware/gralloc.h>
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+#include "Hwc.h"
+#include "HwcClient.h"
+#include "IComposerCommandBuffer.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace implementation {
+
+namespace {
+
+class HandleImporter {
+public:
+    HandleImporter() : mInitialized(false) {}
+
+    bool initialize()
+    {
+        // allow only one client
+        if (mInitialized) {
+            return false;
+        }
+
+        if (!openGralloc()) {
+            return false;
+        }
+
+        mInitialized = true;
+        return true;
+    }
+
+    void cleanup()
+    {
+        if (!mInitialized) {
+            return;
+        }
+
+        closeGralloc();
+        mInitialized = false;
+    }
+
+    // In IComposer, any buffer_handle_t is owned by the caller and we need to
+    // make a clone for hwcomposer2.  We also need to translate empty handle
+    // to nullptr.  This function does that, in-place.
+    bool importBuffer(buffer_handle_t& handle)
+    {
+        if (!handle) {
+            return true;
+        }
+
+        if (!handle->numFds && !handle->numInts) {
+            handle = nullptr;
+            return true;
+        }
+
+        buffer_handle_t clone = cloneBuffer(handle);
+        if (!clone) {
+            return false;
+        }
+
+        handle = clone;
+        return true;
+    }
+
+    void freeBuffer(buffer_handle_t handle)
+    {
+        if (!handle) {
+            return;
+        }
+
+        releaseBuffer(handle);
+    }
+
+private:
+    bool mInitialized;
+
+    // Some existing gralloc drivers do not support retaining more than once,
+    // when we are in passthrough mode.
+#ifdef BINDERIZED
+    bool openGralloc()
+    {
+        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 false;
+        }
+
+        uint8_t major = (module->module_api_version >> 8) & 0xff;
+        if (major > 1) {
+            ALOGE("unknown gralloc module major version %d", major);
+            return false;
+        }
+
+        if (major == 1) {
+            err = gralloc1_open(module, &mDevice);
+            if (err) {
+                ALOGE("failed to open gralloc1 device");
+                return false;
+            }
+
+            mRetain = reinterpret_cast<GRALLOC1_PFN_RETAIN>(
+                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RETAIN));
+            mRelease = reinterpret_cast<GRALLOC1_PFN_RELEASE>(
+                    mDevice->getFunction(mDevice, GRALLOC1_FUNCTION_RELEASE));
+            if (!mRetain || !mRelease) {
+                ALOGE("invalid gralloc1 device");
+                gralloc1_close(mDevice);
+                return false;
+            }
+        } else {
+            mModule = reinterpret_cast<const gralloc_module_t*>(module);
+        }
+
+        return true;
+    }
+
+    void closeGralloc()
+    {
+        if (mDevice) {
+            gralloc1_close(mDevice);
+        }
+    }
+
+    buffer_handle_t cloneBuffer(buffer_handle_t handle)
+    {
+        native_handle_t* clone = native_handle_clone(handle);
+        if (!clone) {
+            ALOGE("failed to clone buffer %p", handle);
+            return nullptr;
+        }
+
+        bool err;
+        if (mDevice) {
+            err = (mRetain(mDevice, clone) != GRALLOC1_ERROR_NONE);
+        } else {
+            err = (mModule->registerBuffer(mModule, clone) != 0);
+        }
+
+        if (err) {
+            ALOGE("failed to retain/register buffer %p", clone);
+            native_handle_close(clone);
+            native_handle_delete(clone);
+            return nullptr;
+        }
+
+        return clone;
+    }
+
+    void releaseBuffer(buffer_handle_t handle)
+    {
+        if (mDevice) {
+            mRelease(mDevice, handle);
+        } else {
+            mModule->unregisterBuffer(mModule, handle);
+        }
+        native_handle_close(handle);
+        native_handle_delete(const_cast<native_handle_t*>(handle));
+    }
+
+    // gralloc1
+    gralloc1_device_t* mDevice;
+    GRALLOC1_PFN_RETAIN mRetain;
+    GRALLOC1_PFN_RELEASE mRelease;
+
+    // gralloc0
+    const gralloc_module_t* mModule;
+#else
+    bool openGralloc() { return true; }
+    void closeGralloc() {}
+    buffer_handle_t cloneBuffer(buffer_handle_t handle) { return handle; }
+    void releaseBuffer(buffer_handle_t) {}
+#endif
+};
+
+HandleImporter sHandleImporter;
+
+} // anonymous namespace
+
+BufferClone::BufferClone()
+    : mHandle(nullptr)
+{
+}
+
+BufferClone::BufferClone(BufferClone&& other)
+{
+    mHandle = other.mHandle;
+    other.mHandle = nullptr;
+}
+
+BufferClone& BufferClone::operator=(buffer_handle_t handle)
+{
+    clear();
+    mHandle = handle;
+    return *this;
+}
+
+BufferClone::~BufferClone()
+{
+    clear();
+}
+
+void BufferClone::clear()
+{
+    if (mHandle) {
+        sHandleImporter.freeBuffer(mHandle);
+    }
+}
+
+HwcClient::HwcClient(HwcHal& hal)
+    : mHal(hal), mReader(*this), mWriter(kWriterInitialSize)
+{
+    if (!sHandleImporter.initialize()) {
+        LOG_ALWAYS_FATAL("failed to initialize handle importer");
+    }
+}
+
+HwcClient::~HwcClient()
+{
+    mHal.enableCallback(false);
+    mHal.removeClient();
+
+    // no need to grab the mutex as any in-flight hwbinder call should keep
+    // the client alive
+    for (const auto& dpy : mDisplayData) {
+        if (!dpy.second.Layers.empty()) {
+            ALOGW("client destroyed with valid layers");
+        }
+        for (const auto& ly : dpy.second.Layers) {
+            mHal.destroyLayer(dpy.first, ly.first);
+        }
+
+        if (dpy.second.IsVirtual) {
+            ALOGW("client destroyed with valid virtual display");
+            mHal.destroyVirtualDisplay(dpy.first);
+        }
+    }
+
+    mDisplayData.clear();
+
+    sHandleImporter.cleanup();
+}
+
+void HwcClient::onHotplug(Display display,
+        IComposerCallback::Connection connected)
+{
+    {
+        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+        if (connected == IComposerCallback::Connection::CONNECTED) {
+            mDisplayData.emplace(display, DisplayData(false));
+        } else if (connected == IComposerCallback::Connection::DISCONNECTED) {
+            mDisplayData.erase(display);
+        }
+    }
+
+    mCallback->onHotplug(display, connected);
+}
+
+void HwcClient::onRefresh(Display display)
+{
+    mCallback->onRefresh(display);
+}
+
+void HwcClient::onVsync(Display display, int64_t timestamp)
+{
+    mCallback->onVsync(display, timestamp);
+}
+
+Return<void> HwcClient::registerCallback(const sp<IComposerCallback>& callback)
+{
+    // no locking as we require this function to be called only once
+    mCallback = callback;
+    mHal.enableCallback(callback != nullptr);
+
+    return Void();
+}
+
+Return<uint32_t> HwcClient::getMaxVirtualDisplayCount()
+{
+    return mHal.getMaxVirtualDisplayCount();
+}
+
+Return<void> HwcClient::createVirtualDisplay(uint32_t width, uint32_t height,
+        PixelFormat formatHint, uint32_t outputBufferSlotCount,
+        createVirtualDisplay_cb hidl_cb)
+{
+    Display display = 0;
+    Error err = mHal.createVirtualDisplay(width, height,
+            &formatHint, &display);
+    if (err == Error::NONE) {
+        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+        auto dpy = mDisplayData.emplace(display, DisplayData(true)).first;
+        dpy->second.OutputBuffers.resize(outputBufferSlotCount);
+    }
+
+    hidl_cb(err, display, formatHint);
+    return Void();
+}
+
+Return<Error> HwcClient::destroyVirtualDisplay(Display display)
+{
+    Error err = mHal.destroyVirtualDisplay(display);
+    if (err == Error::NONE) {
+        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+        mDisplayData.erase(display);
+    }
+
+    return err;
+}
+
+Return<void> HwcClient::createLayer(Display display, uint32_t bufferSlotCount,
+        createLayer_cb hidl_cb)
+{
+    Layer layer = 0;
+    Error err = mHal.createLayer(display, &layer);
+    if (err == Error::NONE) {
+        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+        auto dpy = mDisplayData.find(display);
+        auto ly = dpy->second.Layers.emplace(layer, LayerBuffers()).first;
+        ly->second.Buffers.resize(bufferSlotCount);
+    }
+
+    hidl_cb(err, layer);
+    return Void();
+}
+
+Return<Error> HwcClient::destroyLayer(Display display, Layer layer)
+{
+    Error err = mHal.destroyLayer(display, layer);
+    if (err == Error::NONE) {
+        std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+        auto dpy = mDisplayData.find(display);
+        dpy->second.Layers.erase(layer);
+    }
+
+    return err;
+}
+
+Return<void> HwcClient::getActiveConfig(Display display,
+        getActiveConfig_cb hidl_cb)
+{
+    Config config = 0;
+    Error err = mHal.getActiveConfig(display, &config);
+
+    hidl_cb(err, config);
+    return Void();
+}
+
+Return<Error> HwcClient::getClientTargetSupport(Display display,
+        uint32_t width, uint32_t height,
+        PixelFormat format, Dataspace dataspace)
+{
+    Error err = mHal.getClientTargetSupport(display,
+            width, height, format, dataspace);
+    return err;
+}
+
+Return<void> HwcClient::getColorModes(Display display, getColorModes_cb hidl_cb)
+{
+    hidl_vec<ColorMode> modes;
+    Error err = mHal.getColorModes(display, &modes);
+
+    hidl_cb(err, modes);
+    return Void();
+}
+
+Return<void> HwcClient::getDisplayAttribute(Display display,
+        Config config, Attribute attribute,
+        getDisplayAttribute_cb hidl_cb)
+{
+    int32_t value = 0;
+    Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
+
+    hidl_cb(err, value);
+    return Void();
+}
+
+Return<void> HwcClient::getDisplayConfigs(Display display,
+        getDisplayConfigs_cb hidl_cb)
+{
+    hidl_vec<Config> configs;
+    Error err = mHal.getDisplayConfigs(display, &configs);
+
+    hidl_cb(err, configs);
+    return Void();
+}
+
+Return<void> HwcClient::getDisplayName(Display display,
+        getDisplayName_cb hidl_cb)
+{
+    hidl_string name;
+    Error err = mHal.getDisplayName(display, &name);
+
+    hidl_cb(err, name);
+    return Void();
+}
+
+Return<void> HwcClient::getDisplayType(Display display,
+        getDisplayType_cb hidl_cb)
+{
+    DisplayType type = DisplayType::INVALID;
+    Error err = mHal.getDisplayType(display, &type);
+
+    hidl_cb(err, type);
+    return Void();
+}
+
+Return<void> HwcClient::getDozeSupport(Display display,
+        getDozeSupport_cb hidl_cb)
+{
+    bool support = false;
+    Error err = mHal.getDozeSupport(display, &support);
+
+    hidl_cb(err, support);
+    return Void();
+}
+
+Return<void> HwcClient::getHdrCapabilities(Display display,
+        getHdrCapabilities_cb hidl_cb)
+{
+    hidl_vec<Hdr> types;
+    float max_lumi = 0.0f;
+    float max_avg_lumi = 0.0f;
+    float min_lumi = 0.0f;
+    Error err = mHal.getHdrCapabilities(display, &types,
+            &max_lumi, &max_avg_lumi, &min_lumi);
+
+    hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
+    return Void();
+}
+
+Return<Error> HwcClient::setClientTargetSlotCount(Display display,
+        uint32_t clientTargetSlotCount)
+{
+    std::lock_guard<std::mutex> lock(mDisplayDataMutex);
+
+    auto dpy = mDisplayData.find(display);
+    if (dpy == mDisplayData.end()) {
+        return Error::BAD_DISPLAY;
+    }
+
+    dpy->second.ClientTargets.resize(clientTargetSlotCount);
+
+    return Error::NONE;
+}
+
+Return<Error> HwcClient::setActiveConfig(Display display, Config config)
+{
+    Error err = mHal.setActiveConfig(display, config);
+    return err;
+}
+
+Return<Error> HwcClient::setColorMode(Display display, ColorMode mode)
+{
+    Error err = mHal.setColorMode(display, mode);
+    return err;
+}
+
+Return<Error> HwcClient::setPowerMode(Display display, PowerMode mode)
+{
+    Error err = mHal.setPowerMode(display, mode);
+    return err;
+}
+
+Return<Error> HwcClient::setVsyncEnabled(Display display, Vsync enabled)
+{
+    Error err = mHal.setVsyncEnabled(display, enabled);
+    return err;
+}
+
+Return<Error> HwcClient::setInputCommandQueue(
+        const MQDescriptorSync<uint32_t>& descriptor)
+{
+    std::lock_guard<std::mutex> lock(mCommandMutex);
+    return mReader.setMQDescriptor(descriptor) ?
+        Error::NONE : Error::NO_RESOURCES;
+}
+
+Return<void> HwcClient::getOutputCommandQueue(
+        getOutputCommandQueue_cb hidl_cb)
+{
+    // no locking as we require this function to be called inside
+    // executeCommands_cb
+
+    auto outDescriptor = mWriter.getMQDescriptor();
+    if (outDescriptor) {
+        hidl_cb(Error::NONE, *outDescriptor);
+    } else {
+        hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
+    }
+
+    return Void();
+}
+
+Return<void> HwcClient::executeCommands(uint32_t inLength,
+        const hidl_vec<hidl_handle>& inHandles,
+        executeCommands_cb hidl_cb)
+{
+    std::lock_guard<std::mutex> lock(mCommandMutex);
+
+    bool outChanged = false;
+    uint32_t outLength = 0;
+    hidl_vec<hidl_handle> outHandles;
+
+    if (!mReader.readQueue(inLength, inHandles)) {
+        hidl_cb(Error::BAD_PARAMETER, outChanged, outLength, outHandles);
+        return Void();
+    }
+
+    Error err = mReader.parse();
+    if (err == Error::NONE &&
+            !mWriter.writeQueue(&outChanged, &outLength, &outHandles)) {
+        err = Error::NO_RESOURCES;
+    }
+
+    hidl_cb(err, outChanged, outLength, outHandles);
+
+    mReader.reset();
+    mWriter.reset();
+
+    return Void();
+}
+
+HwcClient::CommandReader::CommandReader(HwcClient& client)
+    : mClient(client), mHal(client.mHal), mWriter(client.mWriter)
+{
+}
+
+Error HwcClient::CommandReader::parse()
+{
+    IComposerClient::Command command;
+    uint16_t length = 0;
+
+    while (!isEmpty()) {
+        if (!beginCommand(&command, &length)) {
+            break;
+        }
+
+        bool parsed = false;
+        switch (command) {
+        case IComposerClient::Command::SELECT_DISPLAY:
+            parsed = parseSelectDisplay(length);
+            break;
+        case IComposerClient::Command::SELECT_LAYER:
+            parsed = parseSelectLayer(length);
+            break;
+        case IComposerClient::Command::SET_COLOR_TRANSFORM:
+            parsed = parseSetColorTransform(length);
+            break;
+        case IComposerClient::Command::SET_CLIENT_TARGET:
+            parsed = parseSetClientTarget(length);
+            break;
+        case IComposerClient::Command::SET_OUTPUT_BUFFER:
+            parsed = parseSetOutputBuffer(length);
+            break;
+        case IComposerClient::Command::VALIDATE_DISPLAY:
+            parsed = parseValidateDisplay(length);
+            break;
+        case IComposerClient::Command::ACCEPT_DISPLAY_CHANGES:
+            parsed = parseAcceptDisplayChanges(length);
+            break;
+        case IComposerClient::Command::PRESENT_DISPLAY:
+            parsed = parsePresentDisplay(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_CURSOR_POSITION:
+            parsed = parseSetLayerCursorPosition(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_BUFFER:
+            parsed = parseSetLayerBuffer(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE:
+            parsed = parseSetLayerSurfaceDamage(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_BLEND_MODE:
+            parsed = parseSetLayerBlendMode(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_COLOR:
+            parsed = parseSetLayerColor(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE:
+            parsed = parseSetLayerCompositionType(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_DATASPACE:
+            parsed = parseSetLayerDataspace(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_DISPLAY_FRAME:
+            parsed = parseSetLayerDisplayFrame(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_PLANE_ALPHA:
+            parsed = parseSetLayerPlaneAlpha(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM:
+            parsed = parseSetLayerSidebandStream(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_SOURCE_CROP:
+            parsed = parseSetLayerSourceCrop(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_TRANSFORM:
+            parsed = parseSetLayerTransform(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_VISIBLE_REGION:
+            parsed = parseSetLayerVisibleRegion(length);
+            break;
+        case IComposerClient::Command::SET_LAYER_Z_ORDER:
+            parsed = parseSetLayerZOrder(length);
+            break;
+        default:
+            parsed = false;
+            break;
+        }
+
+        endCommand();
+
+        if (!parsed) {
+            ALOGE("failed to parse command 0x%x, length %" PRIu16,
+                    command, length);
+            break;
+        }
+    }
+
+    return (isEmpty()) ? Error::NONE : Error::BAD_PARAMETER;
+}
+
+bool HwcClient::CommandReader::parseSelectDisplay(uint16_t length)
+{
+    if (length != CommandWriterBase::kSelectDisplayLength) {
+        return false;
+    }
+
+    mDisplay = read64();
+    mWriter.selectDisplay(mDisplay);
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSelectLayer(uint16_t length)
+{
+    if (length != CommandWriterBase::kSelectLayerLength) {
+        return false;
+    }
+
+    mLayer = read64();
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetColorTransform(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetColorTransformLength) {
+        return false;
+    }
+
+    float matrix[16];
+    for (int i = 0; i < 16; i++) {
+        matrix[i] = readFloat();
+    }
+    auto transform = readSigned();
+
+    auto err = mHal.setColorTransform(mDisplay, matrix, transform);
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetClientTarget(uint16_t length)
+{
+    // 4 parameters followed by N rectangles
+    if ((length - 4) % 4 != 0) {
+        return false;
+    }
+
+    bool useCache = false;
+    auto slot = read();
+    auto clientTarget = readHandle(&useCache);
+    auto fence = readFence();
+    auto dataspace = readSigned();
+    auto damage = readRegion((length - 4) / 4);
+
+    auto err = lookupBuffer(BufferCache::CLIENT_TARGETS,
+            slot, useCache, clientTarget);
+    if (err == Error::NONE) {
+        err = mHal.setClientTarget(mDisplay, clientTarget, fence,
+                dataspace, damage);
+    }
+    if (err != Error::NONE) {
+        close(fence);
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetOutputBuffer(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetOutputBufferLength) {
+        return false;
+    }
+
+    bool useCache = false;
+    auto slot = read();
+    auto outputBuffer = readHandle(&useCache);
+    auto fence = readFence();
+
+    auto err = lookupBuffer(BufferCache::OUTPUT_BUFFERS,
+            slot, useCache, outputBuffer);
+    if (err == Error::NONE) {
+        err = mHal.setOutputBuffer(mDisplay, outputBuffer, fence);
+    }
+    if (err != Error::NONE) {
+        close(fence);
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseValidateDisplay(uint16_t length)
+{
+    if (length != CommandWriterBase::kValidateDisplayLength) {
+        return false;
+    }
+
+    std::vector<Layer> changedLayers;
+    std::vector<IComposerClient::Composition> compositionTypes;
+    uint32_t displayRequestMask = 0x0;
+    std::vector<Layer> requestedLayers;
+    std::vector<uint32_t> requestMasks;
+
+    auto err = mHal.validateDisplay(mDisplay, &changedLayers,
+            &compositionTypes, &displayRequestMask,
+            &requestedLayers, &requestMasks);
+    if (err == Error::NONE) {
+        mWriter.setChangedCompositionTypes(changedLayers,
+                compositionTypes);
+        mWriter.setDisplayRequests(displayRequestMask,
+                requestedLayers, requestMasks);
+    } else {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseAcceptDisplayChanges(uint16_t length)
+{
+    if (length != CommandWriterBase::kAcceptDisplayChangesLength) {
+        return false;
+    }
+
+    auto err = mHal.acceptDisplayChanges(mDisplay);
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parsePresentDisplay(uint16_t length)
+{
+    if (length != CommandWriterBase::kPresentDisplayLength) {
+        return false;
+    }
+
+    int presentFence = -1;
+    std::vector<Layer> layers;
+    std::vector<int> fences;
+    auto err = mHal.presentDisplay(mDisplay, &presentFence, &layers, &fences);
+    if (err == Error::NONE) {
+        mWriter.setPresentFence(presentFence);
+        mWriter.setReleaseFences(layers, fences);
+    } else {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerCursorPosition(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerCursorPositionLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerCursorPosition(mDisplay, mLayer,
+            readSigned(), readSigned());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerBuffer(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerBufferLength) {
+        return false;
+    }
+
+    bool useCache = false;
+    auto slot = read();
+    auto buffer = readHandle(&useCache);
+    auto fence = readFence();
+
+    auto err = lookupBuffer(BufferCache::LAYER_BUFFERS,
+            slot, useCache, buffer);
+    if (err == Error::NONE) {
+        err = mHal.setLayerBuffer(mDisplay, mLayer, buffer, fence);
+    }
+    if (err != Error::NONE) {
+        close(fence);
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerSurfaceDamage(uint16_t length)
+{
+    // N rectangles
+    if (length % 4 != 0) {
+        return false;
+    }
+
+    auto damage = readRegion(length / 4);
+    auto err = mHal.setLayerSurfaceDamage(mDisplay, mLayer, damage);
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerBlendMode(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerBlendModeLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerBlendMode(mDisplay, mLayer, readSigned());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerColor(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerColorLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerColor(mDisplay, mLayer, readColor());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerCompositionType(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerCompositionTypeLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerCompositionType(mDisplay, mLayer, readSigned());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerDataspace(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerDataspaceLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerDataspace(mDisplay, mLayer, readSigned());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerDisplayFrame(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerDisplayFrameLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerDisplayFrame(mDisplay, mLayer, readRect());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerPlaneAlpha(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerPlaneAlphaLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerPlaneAlpha(mDisplay, mLayer, readFloat());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerSidebandStream(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerSidebandStreamLength) {
+        return false;
+    }
+
+    auto stream = readHandle();
+
+    auto err = lookupLayerSidebandStream(stream);
+    if (err == Error::NONE) {
+        err = mHal.setLayerSidebandStream(mDisplay, mLayer, stream);
+    }
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerSourceCrop(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerSourceCropLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerSourceCrop(mDisplay, mLayer, readFRect());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerTransform(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerTransformLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerTransform(mDisplay, mLayer, readSigned());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerVisibleRegion(uint16_t length)
+{
+    // N rectangles
+    if (length % 4 != 0) {
+        return false;
+    }
+
+    auto region = readRegion(length / 4);
+    auto err = mHal.setLayerVisibleRegion(mDisplay, mLayer, region);
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+bool HwcClient::CommandReader::parseSetLayerZOrder(uint16_t length)
+{
+    if (length != CommandWriterBase::kSetLayerZOrderLength) {
+        return false;
+    }
+
+    auto err = mHal.setLayerZOrder(mDisplay, mLayer, read());
+    if (err != Error::NONE) {
+        mWriter.setError(getCommandLoc(), err);
+    }
+
+    return true;
+}
+
+hwc_rect_t HwcClient::CommandReader::readRect()
+{
+    return hwc_rect_t{
+        readSigned(),
+        readSigned(),
+        readSigned(),
+        readSigned(),
+    };
+}
+
+std::vector<hwc_rect_t> HwcClient::CommandReader::readRegion(size_t count)
+{
+    std::vector<hwc_rect_t> region;
+    region.reserve(count);
+    while (count > 0) {
+        region.emplace_back(readRect());
+        count--;
+    }
+
+    return region;
+}
+
+hwc_frect_t HwcClient::CommandReader::readFRect()
+{
+    return hwc_frect_t{
+        readFloat(),
+        readFloat(),
+        readFloat(),
+        readFloat(),
+    };
+}
+
+Error HwcClient::CommandReader::lookupBuffer(BufferCache cache, uint32_t slot,
+        bool useCache, buffer_handle_t& handle)
+{
+    std::lock_guard<std::mutex> lock(mClient.mDisplayDataMutex);
+
+    auto dpy = mClient.mDisplayData.find(mDisplay);
+    if (dpy == mClient.mDisplayData.end()) {
+        return Error::BAD_DISPLAY;
+    }
+
+    BufferClone* clone = nullptr;
+    switch (cache) {
+    case BufferCache::CLIENT_TARGETS:
+        if (slot < dpy->second.ClientTargets.size()) {
+            clone = &dpy->second.ClientTargets[slot];
+        }
+        break;
+    case BufferCache::OUTPUT_BUFFERS:
+        if (slot < dpy->second.OutputBuffers.size()) {
+            clone = &dpy->second.OutputBuffers[slot];
+        }
+        break;
+    case BufferCache::LAYER_BUFFERS:
+        {
+            auto ly = dpy->second.Layers.find(mLayer);
+            if (ly == dpy->second.Layers.end()) {
+                return Error::BAD_LAYER;
+            }
+            if (slot < ly->second.Buffers.size()) {
+                clone = &ly->second.Buffers[slot];
+            }
+        }
+        break;
+    case BufferCache::LAYER_SIDEBAND_STREAMS:
+        {
+            auto ly = dpy->second.Layers.find(mLayer);
+            if (ly == dpy->second.Layers.end()) {
+                return Error::BAD_LAYER;
+            }
+            if (slot == 0) {
+                clone = &ly->second.SidebandStream;
+            }
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (!clone) {
+        ALOGW("invalid buffer slot");
+        return Error::BAD_PARAMETER;
+    }
+
+    // use or update cache
+    if (useCache) {
+        handle = *clone;
+    } else {
+        if (!sHandleImporter.importBuffer(handle)) {
+            return Error::NO_RESOURCES;
+        }
+
+        *clone = handle;
+    }
+
+    return Error::NONE;
+}
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.1/default/HwcClient.h b/graphics/composer/2.1/default/HwcClient.h
new file mode 100644
index 0000000..35a0450
--- /dev/null
+++ b/graphics/composer/2.1/default/HwcClient.h
@@ -0,0 +1,202 @@
+/*
+ * 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_COMPOSER_V2_1_HWC_CLIENT_H
+#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H
+
+#include <mutex>
+#include <unordered_map>
+#include <vector>
+
+#include "Hwc.h"
+#include "IComposerCommandBuffer.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+namespace implementation {
+
+class BufferClone {
+public:
+    BufferClone();
+    BufferClone(BufferClone&& other);
+
+    BufferClone(const BufferClone& other) = delete;
+    BufferClone& operator=(const BufferClone& other) = delete;
+
+    BufferClone& operator=(buffer_handle_t handle);
+    ~BufferClone();
+
+    operator buffer_handle_t() const { return mHandle; }
+
+private:
+    void clear();
+
+    buffer_handle_t mHandle;
+};
+
+class HwcClient : public IComposerClient {
+public:
+    HwcClient(HwcHal& hal);
+    virtual ~HwcClient();
+
+    void onHotplug(Display display, IComposerCallback::Connection connected);
+    void onRefresh(Display display);
+    void onVsync(Display display, int64_t timestamp);
+
+    // IComposerClient interface
+    Return<void> registerCallback(
+            const sp<IComposerCallback>& callback) override;
+    Return<uint32_t> getMaxVirtualDisplayCount() override;
+    Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
+            PixelFormat formatHint, uint32_t outputBufferSlotCount,
+            createVirtualDisplay_cb hidl_cb) override;
+    Return<Error> destroyVirtualDisplay(Display display) override;
+    Return<void> createLayer(Display display, uint32_t bufferSlotCount,
+            createLayer_cb hidl_cb) override;
+    Return<Error> destroyLayer(Display display, Layer layer) override;
+    Return<void> getActiveConfig(Display display,
+            getActiveConfig_cb hidl_cb) override;
+    Return<Error> getClientTargetSupport(Display display,
+            uint32_t width, uint32_t height,
+            PixelFormat format, Dataspace dataspace) override;
+    Return<void> getColorModes(Display display,
+            getColorModes_cb hidl_cb) override;
+    Return<void> getDisplayAttribute(Display display,
+            Config config, Attribute attribute,
+            getDisplayAttribute_cb hidl_cb) override;
+    Return<void> getDisplayConfigs(Display display,
+            getDisplayConfigs_cb hidl_cb) override;
+    Return<void> getDisplayName(Display display,
+            getDisplayName_cb hidl_cb) override;
+    Return<void> getDisplayType(Display display,
+            getDisplayType_cb hidl_cb) override;
+    Return<void> getDozeSupport(Display display,
+            getDozeSupport_cb hidl_cb) override;
+    Return<void> getHdrCapabilities(Display display,
+            getHdrCapabilities_cb hidl_cb) override;
+    Return<Error> setActiveConfig(Display display, Config config) override;
+    Return<Error> setColorMode(Display display, ColorMode mode) override;
+    Return<Error> setPowerMode(Display display, PowerMode mode) override;
+    Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
+    Return<Error> setClientTargetSlotCount(Display display,
+            uint32_t clientTargetSlotCount) override;
+    Return<Error> setInputCommandQueue(
+            const MQDescriptorSync<uint32_t>& descriptor) override;
+    Return<void> getOutputCommandQueue(
+            getOutputCommandQueue_cb hidl_cb) override;
+    Return<void> executeCommands(uint32_t inLength,
+            const hidl_vec<hidl_handle>& inHandles,
+            executeCommands_cb hidl_cb) override;
+
+private:
+    struct LayerBuffers {
+        std::vector<BufferClone> Buffers;
+        BufferClone SidebandStream;
+    };
+
+    struct DisplayData {
+        bool IsVirtual;
+
+        std::vector<BufferClone> ClientTargets;
+        std::vector<BufferClone> OutputBuffers;
+
+        std::unordered_map<Layer, LayerBuffers> Layers;
+
+        DisplayData(bool isVirtual) : IsVirtual(isVirtual) {}
+    };
+
+    class CommandReader : public CommandReaderBase {
+    public:
+        CommandReader(HwcClient& client);
+        Error parse();
+
+    private:
+        bool parseSelectDisplay(uint16_t length);
+        bool parseSelectLayer(uint16_t length);
+        bool parseSetColorTransform(uint16_t length);
+        bool parseSetClientTarget(uint16_t length);
+        bool parseSetOutputBuffer(uint16_t length);
+        bool parseValidateDisplay(uint16_t length);
+        bool parseAcceptDisplayChanges(uint16_t length);
+        bool parsePresentDisplay(uint16_t length);
+        bool parseSetLayerCursorPosition(uint16_t length);
+        bool parseSetLayerBuffer(uint16_t length);
+        bool parseSetLayerSurfaceDamage(uint16_t length);
+        bool parseSetLayerBlendMode(uint16_t length);
+        bool parseSetLayerColor(uint16_t length);
+        bool parseSetLayerCompositionType(uint16_t length);
+        bool parseSetLayerDataspace(uint16_t length);
+        bool parseSetLayerDisplayFrame(uint16_t length);
+        bool parseSetLayerPlaneAlpha(uint16_t length);
+        bool parseSetLayerSidebandStream(uint16_t length);
+        bool parseSetLayerSourceCrop(uint16_t length);
+        bool parseSetLayerTransform(uint16_t length);
+        bool parseSetLayerVisibleRegion(uint16_t length);
+        bool parseSetLayerZOrder(uint16_t length);
+
+        hwc_rect_t readRect();
+        std::vector<hwc_rect_t> readRegion(size_t count);
+        hwc_frect_t readFRect();
+
+        enum class BufferCache {
+            CLIENT_TARGETS,
+            OUTPUT_BUFFERS,
+            LAYER_BUFFERS,
+            LAYER_SIDEBAND_STREAMS,
+        };
+        Error lookupBuffer(BufferCache cache, uint32_t slot,
+                bool useCache, buffer_handle_t& handle);
+
+        Error lookupLayerSidebandStream(buffer_handle_t& handle)
+        {
+            return lookupBuffer(BufferCache::LAYER_SIDEBAND_STREAMS,
+                    0, false, handle);
+        }
+
+        HwcClient& mClient;
+        HwcHal& mHal;
+        CommandWriterBase& mWriter;
+
+        Display mDisplay;
+        Layer mLayer;
+    };
+
+    HwcHal& mHal;
+
+    // 64KiB minus a small space for metadata such as read/write pointers
+    static constexpr size_t kWriterInitialSize =
+        64 * 1024 / sizeof(uint32_t) - 16;
+    std::mutex mCommandMutex;
+    CommandReader mReader;
+    CommandWriterBase mWriter;
+
+    sp<IComposerCallback> mCallback;
+
+    std::mutex mDisplayDataMutex;
+    std::unordered_map<Display, DisplayData> mDisplayData;
+};
+
+} // namespace implementation
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif  // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_CLIENT_H
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
new file mode 100644
index 0000000..fb78ef8
--- /dev/null
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -0,0 +1,849 @@
+/*
+ * 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_COMPOSER_COMMAND_BUFFER_H
+#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
+
+#ifndef LOG_TAG
+#warn "IComposerCommandBuffer.h included without LOG_TAG"
+#endif
+
+#undef LOG_NDEBUG
+#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <android/hardware/graphics/composer/2.1/IComposer.h>
+#include <log/log.h>
+#include <sync/sync.h>
+#include <fmq/MessageQueue.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_1 {
+
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::MessageQueue;
+
+using CommandQueueType = MessageQueue<uint32_t, kSynchronizedReadWrite>;
+
+// This class helps build a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandWriterBase {
+public:
+    CommandWriterBase(uint32_t initialMaxSize)
+        : mDataMaxSize(initialMaxSize)
+    {
+        mData = std::make_unique<uint32_t[]>(mDataMaxSize);
+        reset();
+    }
+
+    virtual ~CommandWriterBase()
+    {
+        reset();
+    }
+
+    void reset()
+    {
+        mDataWritten = 0;
+        mCommandEnd = 0;
+
+        // handles in mDataHandles are owned by the caller
+        mDataHandles.clear();
+
+        // handles in mTemporaryHandles are owned by the writer
+        for (auto handle : mTemporaryHandles) {
+            native_handle_close(handle);
+            native_handle_delete(handle);
+        }
+        mTemporaryHandles.clear();
+    }
+
+    IComposerClient::Command getCommand(uint32_t offset)
+    {
+        uint32_t val = (offset < mDataWritten) ? mData[offset] : 0;
+        return static_cast<IComposerClient::Command>(val &
+                static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK));
+    }
+
+    bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
+            hidl_vec<hidl_handle>* outCommandHandles)
+    {
+        // write data to queue, optionally resizing it
+        if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
+            if (!mQueue->write(mData.get(), mDataWritten)) {
+                ALOGE("failed to write commands to message queue");
+                return false;
+            }
+
+            *outQueueChanged = false;
+        } else {
+            auto newQueue = std::make_unique<CommandQueueType>(mDataMaxSize);
+            if (!newQueue->isValid() ||
+                    !newQueue->write(mData.get(), mDataWritten)) {
+                ALOGE("failed to prepare a new message queue ");
+                return false;
+            }
+
+            mQueue = std::move(newQueue);
+            *outQueueChanged = true;
+        }
+
+        *outCommandLength = mDataWritten;
+        outCommandHandles->setToExternal(
+                const_cast<hidl_handle*>(mDataHandles.data()),
+                mDataHandles.size());
+
+        return true;
+    }
+
+    const MQDescriptorSync<uint32_t>* getMQDescriptor() const
+    {
+        return (mQueue) ? mQueue->getDesc() : nullptr;
+    }
+
+    static constexpr uint16_t kSelectDisplayLength = 2;
+    void selectDisplay(Display display)
+    {
+        beginCommand(IComposerClient::Command::SELECT_DISPLAY,
+                kSelectDisplayLength);
+        write64(display);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSelectLayerLength = 2;
+    void selectLayer(Layer layer)
+    {
+        beginCommand(IComposerClient::Command::SELECT_LAYER,
+                kSelectLayerLength);
+        write64(layer);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetErrorLength = 2;
+    void setError(uint32_t location, Error error)
+    {
+        beginCommand(IComposerClient::Command::SET_ERROR, kSetErrorLength);
+        write(location);
+        writeSigned(static_cast<int32_t>(error));
+        endCommand();
+    }
+
+    void setChangedCompositionTypes(const std::vector<Layer>& layers,
+            const std::vector<IComposerClient::Composition>& types)
+    {
+        size_t totalLayers = std::min(layers.size(), types.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count = std::min(totalLayers - currentLayer,
+                    static_cast<size_t>(kMaxLength) / 3);
+
+            beginCommand(
+                    IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES,
+                    count * 3);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                writeSigned(static_cast<int32_t>(types[currentLayer + i]));
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    void setDisplayRequests(uint32_t displayRequestMask,
+            const std::vector<Layer>& layers,
+            const std::vector<uint32_t>& layerRequestMasks)
+    {
+        size_t totalLayers = std::min(layers.size(),
+                layerRequestMasks.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count = std::min(totalLayers - currentLayer,
+                    static_cast<size_t>(kMaxLength - 1) / 3);
+
+            beginCommand(IComposerClient::Command::SET_DISPLAY_REQUESTS,
+                    1 + count * 3);
+            write(displayRequestMask);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                write(static_cast<int32_t>(layerRequestMasks[currentLayer + i]));
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    static constexpr uint16_t kSetPresentFenceLength = 1;
+    void setPresentFence(int presentFence)
+    {
+        beginCommand(IComposerClient::Command::SET_PRESENT_FENCE,
+                kSetPresentFenceLength);
+        writeFence(presentFence);
+        endCommand();
+    }
+
+    void setReleaseFences(const std::vector<Layer>& layers,
+            const std::vector<int>& releaseFences)
+    {
+        size_t totalLayers = std::min(layers.size(), releaseFences.size());
+        size_t currentLayer = 0;
+
+        while (currentLayer < totalLayers) {
+            size_t count = std::min(totalLayers - currentLayer,
+                    static_cast<size_t>(kMaxLength) / 3);
+
+            beginCommand(IComposerClient::Command::SET_RELEASE_FENCES,
+                    count * 3);
+            for (size_t i = 0; i < count; i++) {
+                write64(layers[currentLayer + i]);
+                writeFence(releaseFences[currentLayer + i]);
+            }
+            endCommand();
+
+            currentLayer += count;
+        }
+    }
+
+    static constexpr uint16_t kSetColorTransformLength = 17;
+    void setColorTransform(const float* matrix, ColorTransform hint)
+    {
+        beginCommand(IComposerClient::Command::SET_COLOR_TRANSFORM,
+                kSetColorTransformLength);
+        for (int i = 0; i < 16; i++) {
+            writeFloat(matrix[i]);
+        }
+        writeSigned(static_cast<int32_t>(hint));
+        endCommand();
+    }
+
+    void setClientTarget(uint32_t slot, const native_handle_t* target,
+            int acquireFence, Dataspace dataspace,
+            const std::vector<IComposerClient::Rect>& damage)
+    {
+        bool doWrite = (damage.size() <= (kMaxLength - 4) / 4);
+        size_t length = 4 + ((doWrite) ? damage.size() * 4 : 0);
+
+        beginCommand(IComposerClient::Command::SET_CLIENT_TARGET, length);
+        write(slot);
+        writeHandle(target, true);
+        writeFence(acquireFence);
+        writeSigned(static_cast<int32_t>(dataspace));
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // client target is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetOutputBufferLength = 3;
+    void setOutputBuffer(uint32_t slot, const native_handle_t* buffer,
+            int releaseFence)
+    {
+        beginCommand(IComposerClient::Command::SET_OUTPUT_BUFFER,
+                kSetOutputBufferLength);
+        write(slot);
+        writeHandle(buffer, true);
+        writeFence(releaseFence);
+        endCommand();
+    }
+
+    static constexpr uint16_t kValidateDisplayLength = 0;
+    void validateDisplay()
+    {
+        beginCommand(IComposerClient::Command::VALIDATE_DISPLAY,
+                kValidateDisplayLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kAcceptDisplayChangesLength = 0;
+    void acceptDisplayChanges()
+    {
+        beginCommand(IComposerClient::Command::ACCEPT_DISPLAY_CHANGES,
+                kAcceptDisplayChangesLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kPresentDisplayLength = 0;
+    void presentDisplay()
+    {
+        beginCommand(IComposerClient::Command::PRESENT_DISPLAY,
+                kPresentDisplayLength);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerCursorPositionLength = 2;
+    void setLayerCursorPosition(int32_t x, int32_t y)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_CURSOR_POSITION,
+                kSetLayerCursorPositionLength);
+        writeSigned(x);
+        writeSigned(y);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerBufferLength = 3;
+    void setLayerBuffer(uint32_t slot, const native_handle_t* buffer,
+            int acquireFence)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_BUFFER,
+                kSetLayerBufferLength);
+        write(slot);
+        writeHandle(buffer, true);
+        writeFence(acquireFence);
+        endCommand();
+    }
+
+    void setLayerSurfaceDamage(
+            const std::vector<IComposerClient::Rect>& damage)
+    {
+        bool doWrite = (damage.size() <= kMaxLength / 4);
+        size_t length = (doWrite) ? damage.size() * 4 : 0;
+
+        beginCommand(IComposerClient::Command::SET_LAYER_SURFACE_DAMAGE,
+                length);
+        // When there are too many rectangles in the damage region and doWrite
+        // is false, we write no rectangle at all which means the entire
+        // layer is damaged.
+        if (doWrite) {
+            writeRegion(damage);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerBlendModeLength = 1;
+    void setLayerBlendMode(IComposerClient::BlendMode mode)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_BLEND_MODE,
+                kSetLayerBlendModeLength);
+        writeSigned(static_cast<int32_t>(mode));
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerColorLength = 1;
+    void setLayerColor(IComposerClient::Color color)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_COLOR,
+                kSetLayerColorLength);
+        writeColor(color);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerCompositionTypeLength = 1;
+    void setLayerCompositionType(IComposerClient::Composition type)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_COMPOSITION_TYPE,
+                kSetLayerCompositionTypeLength);
+        writeSigned(static_cast<int32_t>(type));
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerDataspaceLength = 1;
+    void setLayerDataspace(Dataspace dataspace)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_DATASPACE,
+                kSetLayerDataspaceLength);
+        writeSigned(static_cast<int32_t>(dataspace));
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerDisplayFrameLength = 4;
+    void setLayerDisplayFrame(const IComposerClient::Rect& frame)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_DISPLAY_FRAME,
+                kSetLayerDisplayFrameLength);
+        writeRect(frame);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerPlaneAlphaLength = 1;
+    void setLayerPlaneAlpha(float alpha)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_PLANE_ALPHA,
+                kSetLayerPlaneAlphaLength);
+        writeFloat(alpha);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerSidebandStreamLength = 1;
+    void setLayerSidebandStream(const native_handle_t* stream)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_SIDEBAND_STREAM,
+                kSetLayerSidebandStreamLength);
+        writeHandle(stream);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerSourceCropLength = 4;
+    void setLayerSourceCrop(const IComposerClient::FRect& crop)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_SOURCE_CROP,
+                kSetLayerSourceCropLength);
+        writeFRect(crop);
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerTransformLength = 1;
+    void setLayerTransform(Transform transform)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_TRANSFORM,
+                kSetLayerTransformLength);
+        writeSigned(static_cast<int32_t>(transform));
+        endCommand();
+    }
+
+    void setLayerVisibleRegion(
+            const std::vector<IComposerClient::Rect>& visible)
+    {
+        bool doWrite = (visible.size() <= kMaxLength / 4);
+        size_t length = (doWrite) ? visible.size() * 4 : 0;
+
+        beginCommand(IComposerClient::Command::SET_LAYER_VISIBLE_REGION,
+                length);
+        // When there are too many rectangles in the visible region and
+        // doWrite is false, we write no rectangle at all which means the
+        // entire layer is visible.
+        if (doWrite) {
+            writeRegion(visible);
+        }
+        endCommand();
+    }
+
+    static constexpr uint16_t kSetLayerZOrderLength = 1;
+    void setLayerZOrder(uint32_t z)
+    {
+        beginCommand(IComposerClient::Command::SET_LAYER_Z_ORDER,
+                kSetLayerZOrderLength);
+        write(z);
+        endCommand();
+    }
+
+protected:
+    void beginCommand(IComposerClient::Command command, uint16_t length)
+    {
+        if (mCommandEnd) {
+            LOG_FATAL("endCommand was not called before command 0x%x",
+                    command);
+        }
+
+        growData(1 + length);
+        write(static_cast<uint32_t>(command) | length);
+
+        mCommandEnd = mDataWritten + length;
+    }
+
+    void endCommand()
+    {
+        if (!mCommandEnd) {
+            LOG_FATAL("beginCommand was not called");
+        } else if (mDataWritten > mCommandEnd) {
+            LOG_FATAL("too much data written");
+            mDataWritten = mCommandEnd;
+        } else if (mDataWritten < mCommandEnd) {
+            LOG_FATAL("too little data written");
+            while (mDataWritten < mCommandEnd) {
+                write(0);
+            }
+        }
+
+        mCommandEnd = 0;
+    }
+
+    void write(uint32_t val)
+    {
+        mData[mDataWritten++] = val;
+    }
+
+    void writeSigned(int32_t val)
+    {
+        memcpy(&mData[mDataWritten++], &val, sizeof(val));
+    }
+
+    void writeFloat(float val)
+    {
+        memcpy(&mData[mDataWritten++], &val, sizeof(val));
+    }
+
+    void write64(uint64_t val)
+    {
+        uint32_t lo = static_cast<uint32_t>(val & 0xffffffff);
+        uint32_t hi = static_cast<uint32_t>(val >> 32);
+        write(lo);
+        write(hi);
+    }
+
+    void writeRect(const IComposerClient::Rect& rect)
+    {
+        writeSigned(rect.left);
+        writeSigned(rect.top);
+        writeSigned(rect.right);
+        writeSigned(rect.bottom);
+    }
+
+    void writeRegion(const std::vector<IComposerClient::Rect>& region)
+    {
+        for (const auto& rect : region) {
+            writeRect(rect);
+        }
+    }
+
+    void writeFRect(const IComposerClient::FRect& rect)
+    {
+        writeFloat(rect.left);
+        writeFloat(rect.top);
+        writeFloat(rect.right);
+        writeFloat(rect.bottom);
+    }
+
+    void writeColor(const IComposerClient::Color& color)
+    {
+        write((color.r <<  0) |
+              (color.g <<  8) |
+              (color.b << 16) |
+              (color.a << 24));
+    }
+
+    // ownership of handle is not transferred
+    void writeHandle(const native_handle_t* handle, bool useCache)
+    {
+        if (!handle) {
+            writeSigned(static_cast<int32_t>((useCache) ?
+                        IComposerClient::HandleIndex::CACHED :
+                        IComposerClient::HandleIndex::EMPTY));
+            return;
+        }
+
+        mDataHandles.push_back(handle);
+        writeSigned(mDataHandles.size() - 1);
+    }
+
+    void writeHandle(const native_handle_t* handle)
+    {
+        writeHandle(handle, false);
+    }
+
+    // ownership of fence is transferred
+    void writeFence(int fence)
+    {
+        native_handle_t* handle = nullptr;
+        if (fence >= 0) {
+            handle = getTemporaryHandle(1, 0);
+            if (handle) {
+                handle->data[0] = fence;
+            } else {
+                ALOGW("failed to get temporary handle for fence %d", fence);
+                sync_wait(fence, -1);
+                close(fence);
+            }
+        }
+
+        writeHandle(handle);
+    }
+
+    native_handle_t* getTemporaryHandle(int numFds, int numInts)
+    {
+        native_handle_t* handle = native_handle_create(numFds, numInts);
+        if (handle) {
+            mTemporaryHandles.push_back(handle);
+        }
+        return handle;
+    }
+
+    static constexpr uint16_t kMaxLength =
+        std::numeric_limits<uint16_t>::max();
+
+private:
+    void growData(uint32_t grow)
+    {
+        uint32_t newWritten = mDataWritten + grow;
+        if (newWritten < mDataWritten) {
+            LOG_ALWAYS_FATAL("buffer overflowed; data written %" PRIu32
+                    ", growing by %" PRIu32, mDataWritten, grow);
+        }
+
+        if (newWritten <= mDataMaxSize) {
+            return;
+        }
+
+        uint32_t newMaxSize = mDataMaxSize << 1;
+        if (newMaxSize < newWritten) {
+            newMaxSize = newWritten;
+        }
+
+        auto newData = std::make_unique<uint32_t[]>(newMaxSize);
+        std::copy_n(mData.get(), mDataWritten, newData.get());
+        mDataMaxSize = newMaxSize;
+        mData = std::move(newData);
+    }
+
+    uint32_t mDataMaxSize;
+    std::unique_ptr<uint32_t[]> mData;
+
+    uint32_t mDataWritten;
+    // end offset of the current command
+    uint32_t mCommandEnd;
+
+    std::vector<hidl_handle> mDataHandles;
+    std::vector<native_handle_t *> mTemporaryHandles;
+
+    std::unique_ptr<CommandQueueType> mQueue;
+};
+
+// This class helps parse a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandReaderBase {
+public:
+    CommandReaderBase() : mDataMaxSize(0)
+    {
+        reset();
+    }
+
+    bool setMQDescriptor(const MQDescriptorSync<uint32_t>& descriptor)
+    {
+        mQueue = std::make_unique<CommandQueueType>(descriptor, false);
+        if (mQueue->isValid()) {
+            return true;
+        } else {
+            mQueue = nullptr;
+            return false;
+        }
+    }
+
+    bool readQueue(uint32_t commandLength,
+            const hidl_vec<hidl_handle>& commandHandles)
+    {
+        if (!mQueue) {
+            return false;
+        }
+
+        auto quantumCount = mQueue->getQuantumCount();
+        if (mDataMaxSize < quantumCount) {
+            mDataMaxSize = quantumCount;
+            mData = std::make_unique<uint32_t[]>(mDataMaxSize);
+        }
+
+        if (commandLength > mDataMaxSize ||
+                !mQueue->read(mData.get(), commandLength)) {
+            ALOGE("failed to read commands from message queue");
+            return false;
+        }
+
+        mDataSize = commandLength;
+        mDataRead = 0;
+        mCommandBegin = 0;
+        mCommandEnd = 0;
+        mDataHandles.setToExternal(
+                const_cast<hidl_handle*>(commandHandles.data()),
+                commandHandles.size());
+
+        return true;
+    }
+
+    void reset()
+    {
+        mDataSize = 0;
+        mDataRead = 0;
+        mCommandBegin = 0;
+        mCommandEnd = 0;
+        mDataHandles.setToExternal(nullptr, 0);
+    }
+
+protected:
+    bool isEmpty() const
+    {
+        return (mDataRead >= mDataSize);
+    }
+
+    bool beginCommand(IComposerClient::Command* outCommand,
+            uint16_t* outLength)
+    {
+        if (mCommandEnd) {
+            LOG_FATAL("endCommand was not called for last command");
+        }
+
+        constexpr uint32_t opcode_mask =
+            static_cast<uint32_t>(IComposerClient::Command::OPCODE_MASK);
+        constexpr uint32_t length_mask =
+            static_cast<uint32_t>(IComposerClient::Command::LENGTH_MASK);
+
+        uint32_t val = read();
+        *outCommand = static_cast<IComposerClient::Command>(
+                val & opcode_mask);
+        *outLength = static_cast<uint16_t>(val & length_mask);
+
+        if (mDataRead + *outLength > mDataSize) {
+            ALOGE("command 0x%x has invalid command length %" PRIu16,
+                    *outCommand, *outLength);
+            // undo the read() above
+            mDataRead--;
+            return false;
+        }
+
+        mCommandEnd = mDataRead + *outLength;
+
+        return true;
+    }
+
+    void endCommand()
+    {
+        if (!mCommandEnd) {
+            LOG_FATAL("beginCommand was not called");
+        } else if (mDataRead > mCommandEnd) {
+            LOG_FATAL("too much data read");
+            mDataRead = mCommandEnd;
+        } else if (mDataRead < mCommandEnd) {
+            LOG_FATAL("too little data read");
+            mDataRead = mCommandEnd;
+        }
+
+        mCommandBegin = mCommandEnd;
+        mCommandEnd = 0;
+    }
+
+    uint32_t getCommandLoc() const
+    {
+        return mCommandBegin;
+    }
+
+    uint32_t read()
+    {
+        return mData[mDataRead++];
+    }
+
+    int32_t readSigned()
+    {
+        int32_t val;
+        memcpy(&val, &mData[mDataRead++], sizeof(val));
+        return val;
+    }
+
+    float readFloat()
+    {
+        float val;
+        memcpy(&val, &mData[mDataRead++], sizeof(val));
+        return val;
+    }
+
+    uint64_t read64()
+    {
+        uint32_t lo = read();
+        uint32_t hi = read();
+        return (static_cast<uint64_t>(hi) << 32) | lo;
+    }
+
+    IComposerClient::Color readColor()
+    {
+        uint32_t val = read();
+        return IComposerClient::Color{
+            static_cast<uint8_t>((val >>  0) & 0xff),
+            static_cast<uint8_t>((val >>  8) & 0xff),
+            static_cast<uint8_t>((val >> 16) & 0xff),
+            static_cast<uint8_t>((val >> 24) & 0xff),
+        };
+    }
+
+    // ownership of handle is not transferred
+    const native_handle_t* readHandle(bool* outUseCache)
+    {
+        const native_handle_t* handle = nullptr;
+
+        int32_t index = readSigned();
+        switch (index) {
+        case static_cast<int32_t>(IComposerClient::HandleIndex::EMPTY):
+            *outUseCache = false;
+            break;
+        case static_cast<int32_t>(IComposerClient::HandleIndex::CACHED):
+            *outUseCache = true;
+            break;
+        default:
+            if (static_cast<size_t>(index) < mDataHandles.size()) {
+                handle = mDataHandles[index].getNativeHandle();
+            } else {
+                ALOGE("invalid handle index %zu", static_cast<size_t>(index));
+            }
+            *outUseCache = false;
+            break;
+        }
+
+        return handle;
+    }
+
+    const native_handle_t* readHandle()
+    {
+        bool useCache;
+        return readHandle(&useCache);
+    }
+
+    // ownership of fence is transferred
+    int readFence()
+    {
+        auto handle = readHandle();
+        if (!handle || handle->numFds == 0) {
+            return -1;
+        }
+
+        if (handle->numFds != 1) {
+            ALOGE("invalid fence handle with %d fds", handle->numFds);
+            return -1;
+        }
+
+        int fd = dup(handle->data[0]);
+        if (fd < 0) {
+            ALOGW("failed to dup fence %d", handle->data[0]);
+            sync_wait(handle->data[0], -1);
+            fd = -1;
+        }
+
+        return fd;
+    }
+
+private:
+    std::unique_ptr<CommandQueueType> mQueue;
+    uint32_t mDataMaxSize;
+    std::unique_ptr<uint32_t[]> mData;
+
+    uint32_t mDataSize;
+    uint32_t mDataRead;
+
+    // begin/end offsets of the current command
+    uint32_t mCommandBegin;
+    uint32_t mCommandEnd;
+
+    hidl_vec<hidl_handle> mDataHandles;
+};
+
+} // namespace V2_1
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_COMMAND_BUFFER_H
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
new file mode 100644
index 0000000..fc21d59
--- /dev/null
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -0,0 +1,5 @@
+service hwcomposer-2-1 /system/bin/hw/android.hardware.graphics.composer@2.1-service
+    class hal
+    user system
+    group graphics drmrpc readproc
+    onrestart restart surfaceflinger
diff --git a/graphics/composer/2.1/default/service.cpp b/graphics/composer/2.1/default/service.cpp
new file mode 100644
index 0000000..c2a2b19
--- /dev/null
+++ b/graphics/composer/2.1/default/service.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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 "HWComposerService"
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/StrongPointer.h>
+#include "Hwc.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::sp;
+using android::hardware::graphics::composer::V2_1::IComposer;
+using android::hardware::graphics::composer::V2_1::implementation::HIDL_FETCH_IComposer;
+
+int main()
+{
+    const char instance[] = "hwcomposer";
+
+    ALOGI("Service is starting.");
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+    sp<IComposer> service = HIDL_FETCH_IComposer(instance);
+    if (service == nullptr) {
+        ALOGI("getService returned NULL");
+        return -1;
+    }
+
+    LOG_FATAL_IF(service->isRemote(), "Service is REMOTE!");
+
+    service->registerAsService(instance);
+
+    // the conventional HAL might start binder services
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(4);
+    android::ProcessState::self()->startThreadPool();
+
+    joinRpcThreadpool();
+
+    return 0;
+}
diff --git a/graphics/composer/2.1/types.hal b/graphics/composer/2.1/types.hal
new file mode 100644
index 0000000..e54031e
--- /dev/null
+++ b/graphics/composer/2.1/types.hal
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.composer@2.1;
+
+/* Return codes from all functions. */
+enum Error : int32_t {
+    NONE            = 0, /* no error */
+    BAD_CONFIG      = 1, /* invalid Config */
+    BAD_DISPLAY     = 2, /* invalid Display */
+    BAD_LAYER       = 3, /* invalid Layer */
+    BAD_PARAMETER   = 4, /* invalid width, height, etc. */
+    /* 5 is reserved */
+    NO_RESOURCES    = 6, /* temporary failure due to resource contention */
+    NOT_VALIDATED   = 7, /* validateDisplay has not been called */
+    UNSUPPORTED     = 8, /* permanent failure */
+};
+
+typedef uint32_t Config;
+typedef uint64_t Display;
+typedef uint64_t Layer;
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
new file mode 100644
index 0000000..4adccb9
--- /dev/null
+++ b/graphics/mapper/2.0/Android.bp
@@ -0,0 +1,60 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.graphics.mapper@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.0",
+    srcs: [
+        "types.hal",
+        "IMapper.hal",
+    ],
+    out: [
+        "android/hardware/graphics/mapper/2.0/types.cpp",
+        "android/hardware/graphics/mapper/2.0/MapperAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.graphics.mapper@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.graphics.mapper@2.0",
+    srcs: [
+        "types.hal",
+        "IMapper.hal",
+    ],
+    out: [
+        "android/hardware/graphics/mapper/2.0/types.h",
+        "android/hardware/graphics/mapper/2.0/IMapper.h",
+        "android/hardware/graphics/mapper/2.0/IHwMapper.h",
+        "android/hardware/graphics/mapper/2.0/BnHwMapper.h",
+        "android/hardware/graphics/mapper/2.0/BpHwMapper.h",
+        "android/hardware/graphics/mapper/2.0/BsMapper.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.graphics.mapper@2.0",
+    generated_sources: ["android.hardware.graphics.mapper@2.0_genc++"],
+    generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/graphics/mapper/2.0/Android.mk b/graphics/mapper/2.0/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/graphics/mapper/2.0/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/graphics/mapper/2.0/IMapper.hal b/graphics/mapper/2.0/IMapper.hal
new file mode 100644
index 0000000..21a6dfa
--- /dev/null
+++ b/graphics/mapper/2.0/IMapper.hal
@@ -0,0 +1,323 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.mapper@2.0;
+
+import android.hardware.graphics.common@1.0::PixelFormat;
+import android.hardware.graphics.allocator@2.0;
+
+interface IMapper {
+    struct Rect {
+        int32_t left;
+        int32_t top;
+        int32_t width;
+        int32_t height;
+    };
+
+    /*
+     * Adds a reference to the given buffer handle.
+     *
+     * A buffer handle received from a remote process or exported by
+     * IAllocator::exportHandle is unknown to the mapper. There is also no
+     * guarantee that the buffer's backing store will stay alive. This
+     * function must be called at least once in both cases to intrdouce the
+     * buffer handle to the mapper and to secure the backing store. It may
+     * also be called more than once to increase the reference count if two
+     * components in the same process want to interact with the buffer
+     * independently.
+     *
+     * @param bufferHandle is the buffer to which a reference must be added.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid
+     *                  NO_RESOURCES when it is not possible to add a
+     *                               reference to this buffer at this time
+     */
+    @entry
+    @callflow(next="*")
+    retain(handle bufferHandle) generates (Error error);
+
+    /*
+     * Removes a reference from the given buffer buffer.
+     *
+     * If no references remain, the buffer handle must be freed with
+     * native_handle_close/native_handle_delete by the mapper. When the last
+     * buffer handle referring to a particular backing store is freed, that
+     * backing store must also be freed.
+     *
+     * @param bufferHandle is the buffer from which a reference must be
+     *        removed.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     */
+    @exit
+    release(handle bufferHandle) generates (Error error);
+
+    /*
+     * Gets the width and height of the buffer in pixels.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param bufferHandle is the buffer from which to get the dimensions.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return width is the width of the buffer in pixels.
+     * @return height is the height of the buffer in pixels.
+     */
+    @callflow(next="*")
+    getDimensions(handle bufferHandle)
+       generates (Error error,
+                  uint32_t width,
+                  uint32_t height);
+
+    /*
+     * Gets the format of the buffer.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param bufferHandle is the buffer from which to get format.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return format is the format of the buffer.
+     */
+    @callflow(next="*")
+    getFormat(handle bufferHandle)
+        generates (Error error,
+                   PixelFormat format);
+
+    /*
+     * Gets the number of layers of the buffer.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param bufferHandle is the buffer from which to get format.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return layerCount is the number of layers of the buffer.
+     */
+    @callflow(next="*")
+    getLayerCount(handle bufferHandle)
+       generates (Error error,
+                  uint32_t layerCount);
+
+    /*
+     * Gets the producer usage flags which were used to allocate this buffer.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param bufferHandle is the buffer from which to get the producer usage
+     *        flags.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return usageMask contains the producer usage flags of the buffer.
+     */
+    @callflow(next="*")
+    getProducerUsageMask(handle bufferHandle)
+              generates (Error error,
+                         uint64_t usageMask);
+
+    /*
+     * Gets the consumer usage flags which were used to allocate this buffer.
+     *
+     * See IAllocator::BufferDescriptorInfo for more information.
+     *
+     * @param bufferHandle is the buffer from which to get the consumer usage
+     *        flags.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return usageMask contains the consumer usage flags of the buffer.
+     */
+    @callflow(next="*")
+    getConsumerUsageMask(handle bufferHandle)
+              generates (Error error,
+                         uint64_t usageMask);
+
+    /*
+     * Gets a value that uniquely identifies the backing store of the given
+     * buffer.
+     *
+     * Buffers which share a backing store should return the same value from
+     * this function. If the buffer is present in more than one process, the
+     * backing store value for that buffer is not required to be the same in
+     * every process.
+     *
+     * @param device is the mapper device.
+     * @param bufferHandle is the buffer from which to get the backing store
+     *        identifier.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return store is the backing store identifier for this buffer.
+     */
+    @callflow(next="*")
+    getBackingStore(handle bufferHandle)
+         generates (Error error,
+                    BackingStore store);
+
+    /*
+     * Gets the stride of the buffer in pixels.
+     *
+     * The stride is the offset in pixel-sized elements between the same
+     * column in two adjacent rows of pixels. This may not be equal to the
+     * width of the buffer.
+     *
+     * @param device is the mapper device.
+     * @param bufferHandle is the buffer from which to get the stride.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     *                  UNDEFINED when the notion of a stride is not
+     *                            meaningful for the buffer format.
+     * @return store is the stride in pixels.
+     */
+    @callflow(next="*")
+    getStride(handle bufferHandle)
+        generates (Error error,
+                   uint32_t stride);
+
+    /*
+     * Locks the given buffer for the specified CPU usage.
+     *
+     * Exactly one of producerUsageMask and consumerUsageMask must be 0. The
+     * usage which is not 0 must be one of the *Usage::CPU* values, as
+     * applicable. Locking a buffer for a non-CPU usage is not supported.
+     *
+     * Locking the same buffer simultaneously from multiple threads is
+     * permitted, but if any of the threads attempt to lock the buffer for
+     * writing, the behavior is undefined, except that it must not cause
+     * process termination or block the client indefinitely. Leaving the
+     * buffer content in an indeterminate state or returning an error are both
+     * acceptable.
+     *
+     * The client must not modify the content of the buffer outside of
+     * accessRegion, and the device need not guarantee that content outside of
+     * accessRegion is valid for reading. The result of reading or writing
+     * outside of accessRegion is undefined, except that it must not cause
+     * process termination.
+     *
+     * data will be filled with a pointer to the locked buffer memory. This
+     * address will represent the top-left corner of the entire buffer, even
+     * if accessRegion does not begin at the top-left corner.
+     *
+     * acquireFence is a file descriptor referring to a acquire sync fence
+     * object, which will be signaled when it is safe for the device to access
+     * the contents of the buffer (prior to locking). If it is already safe to
+     * access the buffer contents, -1 may be passed instead.
+     *
+     * @param bufferHandle is the buffer to lock.
+     * @param producerUsageMask contains the producer usage flags to request;
+     *        either this or consumerUsagemask must be 0, and the other must
+     *        be a CPU usage.
+     * @param consumerUsageMask contains the consumer usage flags to request;
+     *        either this or producerUsageMask must be 0, and the other must
+     *        be a CPU usage.
+     * @param accessRegion is the portion of the buffer that the client
+     *        intends to access.
+     * @param acquireFence is a sync fence file descriptor as described above.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     *                  BAD_VALUE when neither or both of producerUsageMask
+     *                            and consumerUsageMask were 0, or the usage
+     *                            which was not 0 was not a CPU usage.
+     *                  NO_RESOURCES when the buffer cannot be locked at this
+     *                               time, but locking may succeed at a future
+     *                               time.
+     *                  UNSUPPORTED when the buffer cannot be locked with the
+     *                              given usage, and any future attempts at
+     *                              locking will also fail.
+     * @return data will be filled with a CPU-accessible pointer to the buffer
+     *         data.
+     */
+    @callflow(next="unlock")
+    lock(handle bufferHandle,
+         uint64_t producerUsageMask,
+         uint64_t consumerUsageMask,
+         Rect accessRegion,
+         handle acquireFence)
+        generates (Error error,
+                   pointer data);
+
+    /*
+     * This is largely the same as lock(), except that instead of returning a
+     * pointer directly to the buffer data, it returns an FlexLayout struct
+     * describing how to access the data planes.
+     *
+     * This function must work on buffers with PixelFormat::YCbCr_*_888 if
+     * supported by the device, as well as with any other formats requested by
+     * multimedia codecs when they are configured with a
+     * flexible-YUV-compatible color format.
+     *
+     * This function may also be called on buffers of other formats, including
+     * non-YUV formats, but if the buffer format is not compatible with a
+     * flexible representation, it may return UNSUPPORTED.
+     *
+     * @param device is the mapper device.
+     * @param bufferHandle is the buffer to lock.
+     * @param producerUsageMask contains the producer usage flags to request;
+     *        either this or consumerUsagemask must be 0, and the other must
+     *        be a CPU usage.
+     * @param consumerUsageMask contains the consumer usage flags to request;
+     *        either this or producerUsageMask must be 0, and the other must
+     *        be a CPU usage.
+     * @param accessRegion is the portion of the buffer that the client
+     *        intends to access.
+     * @param acquireFence is a sync fence file descriptor as described in
+     *        lock().
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     *                  BAD_VALUE when neither or both of producerUsageMask
+     *                            and consumerUsageMask were 0, or the usage
+     *                            which was not 0 was not a CPU usage.
+     *                  NO_RESOURCES when the buffer cannot be locked at this
+     *                               time, but locking may succeed at a future
+     *                               time.
+     *                  UNSUPPORTED when the buffer cannot be locked with the
+     *                              given usage, and any future attempts at
+     *                              locking will also fail.
+     * @return flexLayout will be filled with the description of the planes in
+     *         the buffer.
+     */
+    @callflow(next="unlock")
+    lockFlex(handle bufferHandle,
+             uint64_t producerUsageMask,
+             uint64_t consumerUsageMask,
+             Rect accessRegion,
+             handle acquireFence)
+        generates (Error error,
+                   FlexLayout layout);
+
+    /*
+     * This function indicates to the device that the client will be done with
+     * the buffer when releaseFence signals.
+     *
+     * releaseFence will be filled with a file descriptor referring to a
+     * release sync fence object, which will be signaled when it is safe to
+     * access the contents of the buffer (after the buffer has been unlocked).
+     * If it is already safe to access the buffer contents, then -1 may be
+     * returned instead.
+     *
+     * This function is used to unlock both buffers locked by lock() and those
+     * locked by lockFlex().
+     *
+     * @param device is the mapper device.
+     * @param bufferHandle is the buffer to unlock.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer handle is invalid.
+     * @return releaseFence is a sync fence file descriptor as described
+     *         above.
+     */
+    @callflow(next="*")
+    unlock(handle bufferHandle)
+        generates (Error error,
+                   handle releaseFence);
+};
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
new file mode 100644
index 0000000..c3d2281
--- /dev/null
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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",
+    relative_install_path: "hw",
+    srcs: ["GrallocMapper.cpp"],
+    cppflags: ["-Wall", "-Wextra"],
+    shared_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/graphics/mapper/2.0/default/GrallocMapper.cpp b/graphics/mapper/2.0/default/GrallocMapper.cpp
new file mode 100644
index 0000000..3b6460a
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocMapper.cpp
@@ -0,0 +1,426 @@
+/*
+ * 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 <mutex>
+#include <vector>
+#include <unordered_map>
+
+#include <string.h>
+
+#include <hardware/gralloc1.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+namespace {
+
+using android::hardware::graphics::allocator::V2_0::Error;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class GrallocMapperHal : public IMapper {
+public:
+    GrallocMapperHal(const hw_module_t* module);
+    ~GrallocMapperHal();
+
+    // IMapper interface
+    Return<Error> retain(const hidl_handle& bufferHandle) override;
+    Return<Error> release(const hidl_handle& bufferHandle) override;
+    Return<void> getDimensions(const hidl_handle& bufferHandle,
+            getDimensions_cb hidl_cb) override;
+    Return<void> getFormat(const hidl_handle& bufferHandle,
+            getFormat_cb hidl_cb) override;
+    Return<void> getLayerCount(const hidl_handle& bufferHandle,
+            getLayerCount_cb hidl_cb) override;
+    Return<void> getProducerUsageMask(const hidl_handle& bufferHandle,
+            getProducerUsageMask_cb hidl_cb) override;
+    Return<void> getConsumerUsageMask(const hidl_handle& bufferHandle,
+            getConsumerUsageMask_cb hidl_cb) override;
+    Return<void> getBackingStore(const hidl_handle& bufferHandle,
+            getBackingStore_cb hidl_cb) override;
+    Return<void> getStride(const hidl_handle& bufferHandle,
+            getStride_cb hidl_cb) override;
+    Return<void> lock(const hidl_handle& bufferHandle,
+            uint64_t producerUsageMask, uint64_t consumerUsageMask,
+            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
+            lock_cb hidl_cb) override;
+    Return<void> lockFlex(const hidl_handle& bufferHandle,
+            uint64_t producerUsageMask, uint64_t consumerUsageMask,
+            const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
+            lockFlex_cb hidl_cb) override;
+    Return<void> unlock(const hidl_handle& bufferHandle,
+            unlock_cb hidl_cb) override;
+
+private:
+    void initCapabilities();
+
+    template<typename T>
+    void initDispatch(gralloc1_function_descriptor_t desc, T* outPfn);
+    void initDispatch();
+
+    static gralloc1_rect_t asGralloc1Rect(const IMapper::Rect& rect);
+    static bool dupFence(const hidl_handle& fenceHandle, int* outFd);
+
+    gralloc1_device_t* mDevice;
+
+    struct {
+        bool layeredBuffers;
+    } mCapabilities;
+
+    struct {
+        GRALLOC1_PFN_RETAIN retain;
+        GRALLOC1_PFN_RELEASE release;
+        GRALLOC1_PFN_GET_DIMENSIONS getDimensions;
+        GRALLOC1_PFN_GET_FORMAT getFormat;
+        GRALLOC1_PFN_GET_LAYER_COUNT getLayerCount;
+        GRALLOC1_PFN_GET_PRODUCER_USAGE getProducerUsage;
+        GRALLOC1_PFN_GET_CONSUMER_USAGE getConsumerUsage;
+        GRALLOC1_PFN_GET_BACKING_STORE getBackingStore;
+        GRALLOC1_PFN_GET_STRIDE getStride;
+        GRALLOC1_PFN_GET_NUM_FLEX_PLANES getNumFlexPlanes;
+        GRALLOC1_PFN_LOCK lock;
+        GRALLOC1_PFN_LOCK_FLEX lockFlex;
+        GRALLOC1_PFN_UNLOCK unlock;
+    } mDispatch;
+
+    std::mutex mMutex;
+    std::unordered_map<buffer_handle_t, size_t> mBufferReferenceCounts;
+};
+
+GrallocMapperHal::GrallocMapperHal(const hw_module_t* module)
+    : mDevice(nullptr), mCapabilities(), mDispatch()
+{
+    int status = gralloc1_open(module, &mDevice);
+    if (status) {
+        LOG_ALWAYS_FATAL("failed to open gralloc1 device: %s",
+                strerror(-status));
+    }
+
+    initCapabilities();
+    initDispatch();
+}
+
+GrallocMapperHal::~GrallocMapperHal()
+{
+    gralloc1_close(mDevice);
+}
+
+void GrallocMapperHal::initCapabilities()
+{
+    uint32_t count;
+    mDevice->getCapabilities(mDevice, &count, nullptr);
+
+    std::vector<int32_t> caps(count);
+    mDevice->getCapabilities(mDevice, &count, caps.data());
+    caps.resize(count);
+
+    for (auto cap : caps) {
+        switch (cap) {
+        case GRALLOC1_CAPABILITY_LAYERED_BUFFERS:
+            mCapabilities.layeredBuffers = true;
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+template<typename T>
+void GrallocMapperHal::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 GrallocMapperHal::initDispatch()
+{
+    initDispatch(GRALLOC1_FUNCTION_RETAIN, &mDispatch.retain);
+    initDispatch(GRALLOC1_FUNCTION_RELEASE, &mDispatch.release);
+    initDispatch(GRALLOC1_FUNCTION_GET_DIMENSIONS, &mDispatch.getDimensions);
+    initDispatch(GRALLOC1_FUNCTION_GET_FORMAT, &mDispatch.getFormat);
+    if (mCapabilities.layeredBuffers) {
+        initDispatch(GRALLOC1_FUNCTION_GET_LAYER_COUNT,
+                &mDispatch.getLayerCount);
+    }
+    initDispatch(GRALLOC1_FUNCTION_GET_PRODUCER_USAGE,
+            &mDispatch.getProducerUsage);
+    initDispatch(GRALLOC1_FUNCTION_GET_CONSUMER_USAGE,
+            &mDispatch.getConsumerUsage);
+    initDispatch(GRALLOC1_FUNCTION_GET_BACKING_STORE,
+            &mDispatch.getBackingStore);
+    initDispatch(GRALLOC1_FUNCTION_GET_STRIDE, &mDispatch.getStride);
+    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);
+}
+
+gralloc1_rect_t GrallocMapperHal::asGralloc1Rect(const IMapper::Rect& rect)
+{
+    return gralloc1_rect_t{rect.left, rect.top, rect.width, rect.height};
+}
+
+bool GrallocMapperHal::dupFence(const hidl_handle& fenceHandle, int* outFd)
+{
+    auto handle = fenceHandle.getNativeHandle();
+    if (!handle || handle->numFds == 0) {
+        *outFd = -1;
+        return true;
+    }
+
+    if (handle->numFds > 1) {
+        ALOGE("invalid fence handle with %d fds", handle->numFds);
+        return false;
+    }
+
+    *outFd = dup(handle->data[0]);
+    return (*outFd >= 0);
+}
+
+Return<Error> GrallocMapperHal::retain(const hidl_handle& bufferHandle)
+{
+    int32_t err = mDispatch.retain(mDevice, bufferHandle);
+    if (err == GRALLOC1_ERROR_NONE) {
+        auto nativeHandle = bufferHandle.getNativeHandle();
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        ++mBufferReferenceCounts[nativeHandle];
+    }
+    return static_cast<Error>(err);
+}
+
+Return<Error> GrallocMapperHal::release(const hidl_handle& bufferHandle)
+{
+    int32_t err = mDispatch.release(mDevice, bufferHandle);
+    if (err == GRALLOC1_ERROR_NONE) {
+        auto nativeHandle = bufferHandle.getNativeHandle();
+        std::lock_guard<std::mutex> lock(mMutex);
+
+        auto iter = mBufferReferenceCounts.find(bufferHandle);
+        if (iter == mBufferReferenceCounts.end()) {
+            // this should never happen
+            err = GRALLOC1_ERROR_BAD_HANDLE;
+        } else if (--iter->second == 0) {
+            native_handle_close(nativeHandle);
+            native_handle_delete(const_cast<native_handle_t*>(nativeHandle));
+
+            mBufferReferenceCounts.erase(iter);
+        }
+    }
+
+    return static_cast<Error>(err);
+}
+
+Return<void> GrallocMapperHal::getDimensions(const hidl_handle& bufferHandle,
+        getDimensions_cb hidl_cb)
+{
+    uint32_t width = 0;
+    uint32_t height = 0;
+    int32_t err = mDispatch.getDimensions(mDevice, bufferHandle,
+            &width, &height);
+
+    hidl_cb(static_cast<Error>(err), width, height);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getFormat(const hidl_handle& bufferHandle,
+        getFormat_cb hidl_cb)
+{
+    int32_t format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
+    int32_t err = mDispatch.getFormat(mDevice, bufferHandle, &format);
+
+    hidl_cb(static_cast<Error>(err), static_cast<PixelFormat>(format));
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getLayerCount(const hidl_handle& bufferHandle,
+        getLayerCount_cb hidl_cb)
+{
+    int32_t err = GRALLOC1_ERROR_NONE;
+    uint32_t count = 1;
+    if (mCapabilities.layeredBuffers) {
+        err = mDispatch.getLayerCount(mDevice, bufferHandle, &count);
+    }
+
+    hidl_cb(static_cast<Error>(err), count);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getProducerUsageMask(
+        const hidl_handle& bufferHandle, getProducerUsageMask_cb hidl_cb)
+{
+    uint64_t mask = 0x0;
+    int32_t err = mDispatch.getProducerUsage(mDevice, bufferHandle, &mask);
+
+    hidl_cb(static_cast<Error>(err), mask);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getConsumerUsageMask(
+        const hidl_handle& bufferHandle, getConsumerUsageMask_cb hidl_cb)
+{
+    uint64_t mask = 0x0;
+    int32_t err = mDispatch.getConsumerUsage(mDevice, bufferHandle, &mask);
+
+    hidl_cb(static_cast<Error>(err), mask);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getBackingStore(
+        const hidl_handle& bufferHandle, getBackingStore_cb hidl_cb)
+{
+    uint64_t store = 0;
+    int32_t err = mDispatch.getBackingStore(mDevice, bufferHandle, &store);
+
+    hidl_cb(static_cast<Error>(err), store);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::getStride(const hidl_handle& bufferHandle,
+        getStride_cb hidl_cb)
+{
+    uint32_t stride = 0;
+    int32_t err = mDispatch.getStride(mDevice, bufferHandle, &stride);
+
+    hidl_cb(static_cast<Error>(err), stride);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::lock(const hidl_handle& bufferHandle,
+        uint64_t producerUsageMask, uint64_t consumerUsageMask,
+        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
+        lock_cb hidl_cb)
+{
+    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
+
+    int fence = -1;
+    if (!dupFence(acquireFence, &fence)) {
+        hidl_cb(Error::NO_RESOURCES, nullptr);
+        return Void();
+    }
+
+    void* data = nullptr;
+    int32_t err = mDispatch.lock(mDevice, bufferHandle, producerUsageMask,
+            consumerUsageMask, &rect, &data, fence);
+    if (err != GRALLOC1_ERROR_NONE) {
+        close(fence);
+    }
+
+    hidl_cb(static_cast<Error>(err), data);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::lockFlex(const hidl_handle& bufferHandle,
+        uint64_t producerUsageMask, uint64_t consumerUsageMask,
+        const IMapper::Rect& accessRegion, const hidl_handle& acquireFence,
+        lockFlex_cb hidl_cb)
+{
+    FlexLayout layout_reply{};
+
+    uint32_t planeCount = 0;
+    int32_t err = mDispatch.getNumFlexPlanes(mDevice, bufferHandle,
+            &planeCount);
+    if (err != GRALLOC1_ERROR_NONE) {
+        hidl_cb(static_cast<Error>(err), layout_reply);
+        return Void();
+    }
+
+    gralloc1_rect_t rect = asGralloc1Rect(accessRegion);
+
+    int fence = -1;
+    if (!dupFence(acquireFence, &fence)) {
+        hidl_cb(Error::NO_RESOURCES, layout_reply);
+        return Void();
+    }
+
+    std::vector<android_flex_plane_t> planes(planeCount);
+    android_flex_layout_t layout{};
+    layout.num_planes = planes.size();
+    layout.planes = planes.data();
+
+    err = mDispatch.lockFlex(mDevice, bufferHandle, producerUsageMask,
+            consumerUsageMask, &rect, &layout, fence);
+    if (err == GRALLOC1_ERROR_NONE) {
+        layout_reply.format = static_cast<FlexFormat>(layout.format);
+
+        planes.resize(layout.num_planes);
+        layout_reply.planes.setToExternal(
+                reinterpret_cast<FlexPlane*>(planes.data()), planes.size());
+    } else {
+        close(fence);
+    }
+
+    hidl_cb(static_cast<Error>(err), layout_reply);
+    return Void();
+}
+
+Return<void> GrallocMapperHal::unlock(const hidl_handle& bufferHandle,
+        unlock_cb hidl_cb)
+{
+    int32_t fence = -1;
+    int32_t err = mDispatch.unlock(mDevice, bufferHandle, &fence);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(fenceStorage, 1, 0);
+    hidl_handle fenceHandle;
+    if (err == GRALLOC1_ERROR_NONE && fence >= 0) {
+        auto nativeHandle = native_handle_init(fenceStorage, 1, 0);
+        nativeHandle->data[0] = fence;
+
+        fenceHandle = nativeHandle;
+    }
+
+    hidl_cb(static_cast<Error>(err), fenceHandle);
+    return Void();
+}
+
+} // anonymous namespace
+
+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;
+    if (major != 1) {
+        ALOGE("unknown gralloc module major version %d", major);
+        return nullptr;
+    }
+
+    return new GrallocMapperHal(module);
+}
+
+} // 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
new file mode 100644
index 0000000..a2f89d1
--- /dev/null
+++ b/graphics/mapper/2.0/default/GrallocMapper.h
@@ -0,0 +1,38 @@
+/*
+ * 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>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace implementation {
+
+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/types.hal b/graphics/mapper/2.0/types.hal
new file mode 100644
index 0000000..aa33141
--- /dev/null
+++ b/graphics/mapper/2.0/types.hal
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.mapper@2.0;
+
+/*
+ * Structures for describing flexible YUVA/RGBA formats for consumption by
+ * applications. Such flexible formats contain a plane for each component (e.g.
+ * red, green, blue), where each plane is laid out in a grid-like pattern
+ * occupying unique byte addresses and with consistent byte offsets between
+ * neighboring pixels.
+ *
+ * The FlexLayout structure is used with any pixel format that can be
+ * represented by it, such as:
+ *  - PixelFormat::YCBCR_*_888
+ *  - PixelFormat::FLEX_RGB*_888
+ *  - PixelFormat::RGB[AX]_888[8],BGRA_8888,RGB_888
+ *  - PixelFormat::YV12,Y8,Y16,YCBCR_422_SP/I,YCRCB_420_SP
+ *  - even implementation defined formats that can be represented by
+ *    the structures
+ *
+ * Vertical increment (aka. row increment or stride) describes the distance in
+ * bytes from the first pixel of one row to the first pixel of the next row
+ * (below) for the component plane. This can be negative.
+ *
+ * Horizontal increment (aka. column or pixel increment) describes the distance
+ * in bytes from one pixel to the next pixel (to the right) on the same row for
+ * the component plane. This can be negative.
+ *
+ * Each plane can be subsampled either vertically or horizontally by
+ * a power-of-two factor.
+ *
+ * The bit-depth of each component can be arbitrary, as long as the pixels are
+ * laid out on whole bytes, in native byte-order, using the most significant
+ * bits of each unit.
+ */
+
+enum FlexComponent : int32_t {
+    Y  = 1 << 0, /* luma */
+    CB = 1 << 1, /* chroma blue */
+    CR = 1 << 2, /* chroma red */
+
+    R  = 1 << 10, /* red */
+    G  = 1 << 11, /* green */
+    B  = 1 << 12, /* blue */
+
+    A  = 1 << 30, /* alpha */
+};
+
+enum FlexFormat : int32_t {
+    /* not a flexible format */
+    INVALID = 0x0,
+
+    Y       = FlexComponent:Y,
+    YCBCR   = Y | FlexComponent:CB | FlexComponent:CR,
+    YCBCRA  = YCBCR | FlexComponent:A,
+
+    RGB     = FlexComponent:R | FlexComponent:G | FlexComponent:B,
+    RGBA    = RGB | FlexComponent:A,
+};
+
+struct FlexPlane {
+    /* Pointer to the first byte of the top-left pixel of the plane. */
+    pointer topLeft;
+
+    FlexComponent component;
+
+    /*
+     * Bits allocated for the component in each pixel. Must be a positive
+     * multiple of 8.
+     */
+    int32_t bitsPerComponent;
+
+    /*
+     * Number of the most significant bits used in the format for this
+     * component. Must be between 1 and bitsPerComponent, inclusive.
+     */
+    int32_t bitsUsed;
+
+    /* Horizontal increment. */
+    int32_t hIncrement;
+    /* Vertical increment. */
+    int32_t vIncrement;
+    /* Horizontal subsampling. Must be a positive power of 2. */
+    int32_t hSubsampling;
+    /* Vertical subsampling. Must be a positive power of 2. */
+    int32_t vSubsampling;
+};
+
+struct FlexLayout {
+    /* The kind of flexible format. */
+    FlexFormat format;
+
+    /*
+     * A plane for each component; ordered in increasing component value
+     * order. E.g. FlexFormat::RGBA maps 0 -> R, 1 -> G, etc.  Can have size 0
+     * for FlexFormat::INVALID.
+     */
+    vec<FlexPlane> planes;
+};
+
+/* Backing store ID of a buffer. See IMapper::getBackingStore. */
+typedef uint64_t BackingStore;
diff --git a/graphics/mapper/2.0/vts/Android.mk b/graphics/mapper/2.0/vts/Android.mk
new file mode 100644
index 0000000..6185ddc
--- /dev/null
+++ b/graphics/mapper/2.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/graphics/mapper/hidl/target/Android.mk
diff --git a/graphics/mapper/2.0/vts/Mapper.vts b/graphics/mapper/2.0/vts/Mapper.vts
new file mode 100644
index 0000000..26e049f
--- /dev/null
+++ b/graphics/mapper/2.0/vts/Mapper.vts
@@ -0,0 +1,280 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "IMapper"
+
+package: "android.hardware.graphics.mapper"
+
+import: "android.hardware.graphics.allocator@2.0::types"
+import: "android.hardware.graphics.common@1.0::types"
+import: "android.hardware.graphics.mapper@2.0::types"
+
+interface: {
+    attribute: {
+        name: "::android::hardware::graphics::mapper::V2_0::IMapper::Rect"
+        type: TYPE_STRUCT
+        struct_value: {
+            name: "left"
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        struct_value: {
+            name: "top"
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        struct_value: {
+            name: "width"
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        struct_value: {
+            name: "height"
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "retain"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "release"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "getDimensions"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getFormat"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::common::V1_0::PixelFormat"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getLayerCount"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getProducerUsageMask"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getConsumerUsageMask"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getBackingStore"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getStride"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "lock"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_POINTER
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::graphics::mapper::V2_0::IMapper::Rect"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "unlock"
+        }
+    }
+
+    api: {
+        name: "lockFlex"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::graphics::mapper::V2_0::FlexLayout"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::graphics::mapper::V2_0::IMapper::Rect"
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "unlock"
+        }
+    }
+
+    api: {
+        name: "unlock"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::graphics::allocator::V2_0::Error"
+        }
+        return_type_hidl: {
+            type: TYPE_HANDLE
+        }
+        arg: {
+            type: TYPE_HANDLE
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+}
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..27ea350
--- /dev/null
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -0,0 +1,44 @@
+//
+// 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_test {
+    name: "graphics_mapper_hidl_hal_test",
+    gtest: true,
+    srcs: ["graphics_mapper_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libsync",
+        "libutils",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.common@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage",
+    ],
+}
diff --git a/graphics/mapper/2.0/vts/functional/graphics_mapper_hidl_hal_test.cpp b/graphics/mapper/2.0/vts/functional/graphics_mapper_hidl_hal_test.cpp
new file mode 100644
index 0000000..840da1a
--- /dev/null
+++ b/graphics/mapper/2.0/vts/functional/graphics_mapper_hidl_hal_test.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "graphics_mapper_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+#include <gtest/gtest.h>
+#include <sync/sync.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_0 {
+namespace tests {
+namespace {
+
+using namespace android::hardware::graphics::allocator::V2_0;
+using namespace android::hardware::graphics::common::V1_0;
+
+class GraphicsMapperHidlTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    mAllocator = IAllocator::getService("gralloc");
+    ASSERT_NE(mAllocator, nullptr);
+
+    mAllocator->createClient([this](const auto& error, const auto& client) {
+      if (error == Error::NONE) {
+        mAllocatorClient = client;
+      }
+    });
+    ASSERT_NE(mAllocatorClient, nullptr);
+
+    mMapper = IMapper::getService("gralloc-mapper");
+    ASSERT_NE(nullptr, mMapper.get());
+    ASSERT_FALSE(mMapper->isRemote());
+
+    mDummyDescriptorInfo.width = 64;
+    mDummyDescriptorInfo.height = 64;
+    mDummyDescriptorInfo.layerCount = 1;
+    mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+    mDummyDescriptorInfo.producerUsageMask =
+        static_cast<uint64_t>(ProducerUsage::CPU_WRITE);
+    mDummyDescriptorInfo.consumerUsageMask =
+        static_cast<uint64_t>(ConsumerUsage::CPU_READ);
+  }
+
+  void TearDown() override {}
+
+  const native_handle_t* allocate(
+      const IAllocatorClient::BufferDescriptorInfo& info) {
+    // create descriptor
+    Error err = Error::NO_RESOURCES;
+    BufferDescriptor descriptor;
+    mAllocatorClient->createDescriptor(
+        info, [&](const auto& tmpError, const auto& tmpDescriptor) {
+          err = tmpError;
+          descriptor = tmpDescriptor;
+        });
+    if (err != Error::NONE) {
+      return nullptr;
+    }
+
+    // allocate buffer
+    hidl_vec<BufferDescriptor> descriptors;
+    hidl_vec<Buffer> buffers;
+    descriptors.setToExternal(&descriptor, 1);
+    err = Error::NO_RESOURCES;
+    mAllocatorClient->allocate(
+        descriptors, [&](const auto& tmpError, const auto& tmpBuffers) {
+          err = tmpError;
+          buffers = tmpBuffers;
+        });
+    if ((err != Error::NONE && err != Error::NOT_SHARED) ||
+        buffers.size() != 1) {
+      mAllocatorClient->destroyDescriptor(descriptors[0]);
+      return nullptr;
+    }
+
+    // export handle
+    err = Error::NO_RESOURCES;
+    const native_handle_t* handle = nullptr;
+    mAllocatorClient->exportHandle(
+        descriptors[0], buffers[0],
+        [&](const auto& tmpError, const auto& tmpHandle) {
+          err = tmpError;
+          if (err != Error::NONE) {
+            return;
+          }
+
+          handle = native_handle_clone(tmpHandle);
+          if (!handle) {
+            err = Error::NO_RESOURCES;
+            return;
+          }
+
+          err = mMapper->retain(handle);
+          if (err != Error::NONE) {
+            native_handle_close(handle);
+            native_handle_delete(const_cast<native_handle_t*>(handle));
+            handle = nullptr;
+          }
+        });
+
+    mAllocatorClient->destroyDescriptor(descriptors[0]);
+    mAllocatorClient->free(buffers[0]);
+
+    if (err != Error::NONE) {
+      return nullptr;
+    }
+
+    return handle;
+  }
+
+  sp<IMapper> mMapper;
+
+  IAllocatorClient::BufferDescriptorInfo mDummyDescriptorInfo{};
+
+ private:
+  sp<IAllocator> mAllocator;
+  sp<IAllocatorClient> mAllocatorClient;
+};
+
+/**
+ * Test IMapper::retain and IMapper::release.
+ */
+TEST_F(GraphicsMapperHidlTest, RetainRelease) {
+  const native_handle_t* buffer = allocate(mDummyDescriptorInfo);
+  ASSERT_NE(buffer, nullptr);
+
+  const int maxRefs = 10;
+  for (int i = 0; i < maxRefs; i++) {
+    auto err = mMapper->retain(buffer);
+    EXPECT_EQ(Error::NONE, err);
+  }
+  for (int i = 0; i < maxRefs; i++) {
+    auto err = mMapper->release(buffer);
+    EXPECT_EQ(Error::NONE, err);
+  }
+
+  auto err = mMapper->release(buffer);
+  EXPECT_EQ(Error::NONE, err);
+}
+
+/**
+ * Test IMapper::get* getters.
+ */
+TEST_F(GraphicsMapperHidlTest, Getters) {
+  const native_handle_t* buffer = allocate(mDummyDescriptorInfo);
+  ASSERT_NE(buffer, nullptr);
+
+  Error err = Error::NO_RESOURCES;
+  IAllocatorClient::BufferDescriptorInfo info{};
+  mMapper->getDimensions(buffer, [&](const auto& tmpError, const auto& tmpWidth,
+                                     const auto& tmpHeight) {
+    err = tmpError;
+    info.width = tmpWidth;
+    info.height = tmpHeight;
+  });
+  EXPECT_EQ(Error::NONE, err);
+  mMapper->getFormat(buffer, [&](const auto& tmpError, const auto& tmpFormat) {
+    err = tmpError;
+    info.format = tmpFormat;
+  });
+  EXPECT_EQ(Error::NONE, err);
+  mMapper->getProducerUsageMask(
+      buffer, [&](const auto& tmpError, const auto& tmpUsage) {
+        err = tmpError;
+        info.producerUsageMask = tmpUsage;
+      });
+  EXPECT_EQ(Error::NONE, err);
+  mMapper->getConsumerUsageMask(
+      buffer, [&](const auto& tmpError, const auto& tmpUsage) {
+        err = tmpError;
+        info.consumerUsageMask = tmpUsage;
+      });
+  EXPECT_EQ(Error::NONE, err);
+
+  EXPECT_EQ(mDummyDescriptorInfo.width, info.width);
+  EXPECT_EQ(mDummyDescriptorInfo.height, info.height);
+  EXPECT_EQ(mDummyDescriptorInfo.format, info.format);
+  EXPECT_EQ(mDummyDescriptorInfo.producerUsageMask, info.producerUsageMask);
+  EXPECT_EQ(mDummyDescriptorInfo.consumerUsageMask, info.consumerUsageMask);
+
+  BackingStore store = 0;
+  mMapper->getBackingStore(buffer,
+                           [&](const auto& tmpError, const auto& tmpStore) {
+                             err = tmpError;
+                             store = tmpStore;
+                           });
+  EXPECT_EQ(Error::NONE, err);
+
+  uint32_t stride = 0;
+  mMapper->getStride(buffer, [&](const auto& tmpError, const auto& tmpStride) {
+    err = tmpError;
+    stride = tmpStride;
+  });
+  EXPECT_EQ(Error::NONE, err);
+  EXPECT_LE(info.width, stride);
+
+  err = mMapper->release(buffer);
+  EXPECT_EQ(Error::NONE, err);
+}
+
+/**
+ * Test IMapper::lock and IMapper::unlock.
+ */
+TEST_F(GraphicsMapperHidlTest, LockBasic) {
+  const auto& info = mDummyDescriptorInfo;
+  const native_handle_t* buffer = allocate(info);
+  ASSERT_NE(buffer, nullptr);
+
+  Error err = Error::NO_RESOURCES;
+  uint32_t stride = 0;
+  mMapper->getStride(buffer, [&](const auto& tmpError, const auto& tmpStride) {
+    err = tmpError;
+    stride = tmpStride;
+  });
+  EXPECT_EQ(Error::NONE, err);
+
+  // lock buffer for writing
+  const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                             static_cast<int32_t>(info.height)};
+  hidl_handle acquireFence(nullptr);
+  uint32_t* data;
+  err = Error::NO_RESOURCES;
+  mMapper->lock(buffer, info.producerUsageMask, 0, region, acquireFence,
+          [&](const auto& tmpError, const auto& tmpData) {
+            err = tmpError;
+            data = static_cast<uint32_t*>(tmpData);
+          });
+
+  if (err == Error::NONE) {
+    for (uint32_t y = 0; y < info.height; y++) {
+      for (uint32_t x = 0; x < info.width; x++) {
+        data[stride * y + x] = info.height * y + x;
+      }
+    }
+  } else {
+    EXPECT_EQ(Error::NONE, err);
+  }
+
+  err = Error::NO_RESOURCES;
+  mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+            err = tmpError;
+            auto handle = tmpReleaseFence.getNativeHandle();
+            if (handle && handle->numFds == 1) {
+                sync_wait(handle->data[0], -1);
+                close(handle->data[0]);
+            }
+          });
+  EXPECT_EQ(Error::NONE, err);
+
+  // lock buffer for reading
+  mMapper->lock(buffer, 0, info.consumerUsageMask, region, acquireFence,
+          [&](const auto& tmpError, const auto& tmpData) {
+            err = tmpError;
+            data = static_cast<uint32_t*>(tmpData);
+          });
+  if (err == Error::NONE) {
+    for (uint32_t y = 0; y < info.height; y++) {
+      for (uint32_t x = 0; x < info.width; x++) {
+        EXPECT_EQ(info.height * y + x, data[stride * y + x]);
+      }
+    }
+  } else {
+    EXPECT_EQ(Error::NONE, err);
+  }
+
+  err = Error::NO_RESOURCES;
+  mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+            err = tmpError;
+            auto handle = tmpReleaseFence.getNativeHandle();
+            if (handle && handle->numFds == 1) {
+                sync_wait(handle->data[0], -1);
+                close(handle->data[0]);
+            }
+          });
+  EXPECT_EQ(Error::NONE, err);
+
+  err = mMapper->release(buffer);
+  EXPECT_EQ(Error::NONE, err);
+}
+
+}  // namespace anonymous
+}  // namespace tests
+}  // namespace V2_0
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+
+  return status;
+}
diff --git a/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/Android.mk b/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/Android.mk
new file mode 100644
index 0000000..5f7fae8
--- /dev/null
+++ b/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalGraphicsMapperHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/graphics/mapper/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/AndroidTest.xml b/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..b602ec4
--- /dev/null
+++ b/graphics/mapper/2.0/vts/functional/vts/testcases/hal/graphics/mapper/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Graphics Mapper HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalGraphicsMapperHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/graphics_mapper_hidl_hal_test/graphics_mapper_hidl_hal_test,
+            _64bit::DATA/nativetest64/graphics_mapper_hidl_hal_test/graphics_mapper_hidl_hal_test,
+	    " />
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/graphics/mapper/2.0/vts/types.vts b/graphics/mapper/2.0/vts/types.vts
new file mode 100644
index 0000000..fee8535
--- /dev/null
+++ b/graphics/mapper/2.0/vts/types.vts
@@ -0,0 +1,139 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "types"
+
+package: "android.hardware.graphics.mapper"
+
+
+attribute: {
+    name: "::android::hardware::graphics::mapper::V2_0::FlexComponent"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "Y"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CB"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CR"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "R"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "G"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "B"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "A"
+        scalar_value: {
+            int32_t: 1073741824
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::graphics::mapper::V2_0::FlexFormat"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "Y"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "YCBCR"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "YCBCRA"
+        scalar_value: {
+            int32_t: 1073741831
+        }
+        enumerator: "RGB"
+        scalar_value: {
+            int32_t: 7168
+        }
+        enumerator: "RGBA"
+        scalar_value: {
+            int32_t: 1073748992
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::graphics::mapper::V2_0::FlexPlane"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "topLeft"
+        type: TYPE_POINTER
+    }
+    struct_value: {
+        name: "component"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::graphics::mapper::V2_0::FlexComponent"
+    }
+    struct_value: {
+        name: "bitsPerComponent"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "bitsUsed"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "hIncrement"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "vIncrement"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "hSubsampling"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "vSubsampling"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::graphics::mapper::V2_0::FlexLayout"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::graphics::mapper::V2_0::FlexFormat"
+    }
+    struct_value: {
+        name: "planes"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::graphics::mapper::V2_0::FlexPlane"
+        }
+    }
+}
+
diff --git a/graphics/mapper/Android.mk b/graphics/mapper/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/graphics/mapper/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
new file mode 100644
index 0000000..b0b9549
--- /dev/null
+++ b/health/1.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.health@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.health@1.0",
+    srcs: [
+        "types.hal",
+        "IHealth.hal",
+    ],
+    out: [
+        "android/hardware/health/1.0/types.cpp",
+        "android/hardware/health/1.0/HealthAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.health@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.health@1.0",
+    srcs: [
+        "types.hal",
+        "IHealth.hal",
+    ],
+    out: [
+        "android/hardware/health/1.0/types.h",
+        "android/hardware/health/1.0/IHealth.h",
+        "android/hardware/health/1.0/IHwHealth.h",
+        "android/hardware/health/1.0/BnHwHealth.h",
+        "android/hardware/health/1.0/BpHwHealth.h",
+        "android/hardware/health/1.0/BsHealth.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.health@1.0",
+    generated_sources: ["android.hardware.health@1.0_genc++"],
+    generated_headers: ["android.hardware.health@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.health@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/health/1.0/Android.mk b/health/1.0/Android.mk
new file mode 100644
index 0000000..f05d227
--- /dev/null
+++ b/health/1.0/Android.mk
@@ -0,0 +1,304 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.health@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (BatteryHealth)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/BatteryHealth.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.BatteryHealth
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (BatteryStatus)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/BatteryStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.BatteryStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HealthConfig)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/HealthConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.HealthConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HealthInfo)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/HealthInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.HealthInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHealth.hal
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/IHealth.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHealth.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::IHealth
+
+$(GEN): $(LOCAL_PATH)/IHealth.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.health@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (BatteryHealth)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/BatteryHealth.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.BatteryHealth
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (BatteryStatus)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/BatteryStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.BatteryStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HealthConfig)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/HealthConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.HealthConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HealthInfo)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/HealthInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.HealthInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHealth.hal
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/IHealth.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHealth.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0::IHealth
+
+$(GEN): $(LOCAL_PATH)/IHealth.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.health@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/health/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IHealth.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.health@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/health/1.0/IHealth.hal b/health/1.0/IHealth.hal
new file mode 100644
index 0000000..3828589
--- /dev/null
+++ b/health/1.0/IHealth.hal
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+package android.hardware.health@1.0;
+
+interface IHealth {
+    /**
+     * This function lets you change healthd configuration from default if
+     * desired. It must be called exactly once at startup time.
+     *
+     * The configuration values are described in 'struct HealthConfig'.
+     * To use default configuration, simply return without modifying the
+     * fields of the config parameter.
+     *
+     * @param default healthd configuration.
+     */
+    init(HealthConfig config) generates (HealthConfig configOut);
+
+    /**
+     * This function is a hook to update/change device's HealthInfo (as described
+     * in 'struct HealthInfo').
+     *
+     * 'HealthInfo' describes device's battery and charging status, typically
+     * read from kernel. These values may be modified in this call.
+     *
+     * @param   Device Health info as described in 'struct HealthInfo'.
+     * @return  skipLogging Indication to the caller to add 'or' skip logging the health
+     *          information. Return 'true' to skip logging the update.
+     * @return  infoOut HealthInfo to be sent to client code. (May or may
+     *          not be modified).
+     */
+    update(HealthInfo info) generates (bool skipLogging, HealthInfo infoOut);
+
+    /**
+     * This function is called by healthd when framework queries for remaining
+     * energy in the Battery through BatteryManager APIs.
+     *
+     * @return  result Result of querying enery counter for the battery.
+     * @return  energy Battery remaining energy in nanowatt-hours.
+     *          Must be '0' if result is anything other than Result::SUCCESS.
+     */
+    energyCounter() generates (Result result, int64_t energy);
+};
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
new file mode 100644
index 0000000..89d28cb
--- /dev/null
+++ b/health/1.0/default/Android.mk
@@ -0,0 +1,59 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.health@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
+LOCAL_SRC_FILES := \
+    Health.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    android.hardware.health@1.0 \
+
+LOCAL_STATIC_LIBRARIES := android.hardware.health@1.0-convert
+
+LOCAL_HAL_STATIC_LIBRARIES := libhealthd
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.health@1.0-convert
+LOCAL_SRC_FILES := convert.cpp
+LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    libutils \
+    android.hardware.health@1.0 \
+
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.health@1.0-service
+LOCAL_INIT_RC := android.hardware.health@1.0-service.rc
+LOCAL_SRC_FILES := \
+    HealthService.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.health@1.0 \
+
+include $(BUILD_EXECUTABLE)
+
+include $(call first-makefiles-under,$(LOCAL_PATH))
diff --git a/health/1.0/default/Health.cpp b/health/1.0/default/Health.cpp
new file mode 100644
index 0000000..1a02956
--- /dev/null
+++ b/health/1.0/default/Health.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "health-hal"
+
+#include <Health.h>
+#include <include/hal_conversion.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::health::V1_0::hal_conversion::convertToHealthConfig;
+using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthConfig;
+using ::android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
+using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthInfo;
+
+// Methods from ::android::hardware::health::V1_0::IHealth follow.
+Return<void> Health::init(const HealthConfig& config, init_cb _hidl_cb)  {
+    struct healthd_config healthd_config = {};
+    HealthConfig configOut;
+
+    // To keep working with existing healthd static HALs,
+    // convert the new HealthConfig to the old healthd_config
+    // and back.
+
+    convertFromHealthConfig(config, &healthd_config);
+    healthd_board_init(&healthd_config);
+    mGetEnergyCounter = healthd_config.energyCounter;
+    convertToHealthConfig(&healthd_config, configOut);
+
+    _hidl_cb(configOut);
+
+    return Void();
+}
+
+Return<void> Health::update(const HealthInfo& info, update_cb _hidl_cb)  {
+    struct android::BatteryProperties p = {};
+    HealthInfo infoOut;
+
+    // To keep working with existing healthd static HALs,
+    // convert the new HealthInfo to android::Batteryproperties
+    // and back.
+
+    convertFromHealthInfo(info, &p);
+    int skipLogging = healthd_board_battery_update(&p);
+    convertToHealthInfo(&p, infoOut);
+
+    _hidl_cb(!!skipLogging, infoOut);
+
+    return Void();
+}
+
+Return<void> Health::energyCounter(energyCounter_cb _hidl_cb) {
+    int64_t energy = 0;
+    Result result = Result::NOT_SUPPORTED;
+
+    if (mGetEnergyCounter) {
+        int status = mGetEnergyCounter(&energy);
+        if (status == 0) {
+            result = Result::SUCCESS;
+        }
+    }
+
+    _hidl_cb(result, energy);
+
+   return Void();
+}
+
+IHealth* HIDL_FETCH_IHealth(const char* /* name */) {
+    return new Health();
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/health/1.0/default/Health.h b/health/1.0/default/Health.h
new file mode 100644
index 0000000..ed364c1
--- /dev/null
+++ b/health/1.0/default/Health.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
+#define ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
+
+#include <android/hardware/health/1.0/IHealth.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include <healthd/healthd.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::health::V1_0::HealthInfo;
+using ::android::hardware::health::V1_0::HealthConfig;
+using ::android::hardware::health::V1_0::IHealth;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Health : public IHealth {
+    // Methods from ::android::hardware::health::V1_0::IHealth follow.
+    Return<void> init(const HealthConfig& config, init_cb _hidl_cb)  override;
+    Return<void> update(const HealthInfo& info, update_cb _hidl_cb)  override;
+    Return<void> energyCounter(energyCounter_cb _hidl_cb) override;
+private:
+    std::function<int(int64_t *)> mGetEnergyCounter;
+};
+
+extern "C" IHealth* HIDL_FETCH_IHealth(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
diff --git a/health/1.0/default/HealthService.cpp b/health/1.0/default/HealthService.cpp
new file mode 100644
index 0000000..107f33d
--- /dev/null
+++ b/health/1.0/default/HealthService.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "android.hardware.health@1.0-service"
+
+#include <android/hardware/health/1.0/IHealth.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::health::V1_0::IHealth;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IHealth>("health");
+}
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
new file mode 100644
index 0000000..a0d6a56
--- /dev/null
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -0,0 +1,4 @@
+service health-hal-1-0 /system/bin/hw/android.hardware.health@1.0-service
+    class hal
+    user system
+    group system
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
new file mode 100644
index 0000000..7f1e3c4
--- /dev/null
+++ b/health/1.0/default/convert.cpp
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+#include "include/hal_conversion.h"
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+namespace hal_conversion {
+
+void convertToHealthConfig(const struct healthd_config *hc, HealthConfig& config) {
+    config.periodicChoresIntervalFast = hc->periodic_chores_interval_fast;
+    config.periodicChoresIntervalSlow = hc->periodic_chores_interval_slow;
+
+    config.batteryStatusPath        = hc->batteryStatusPath.string();
+    config.batteryHealthPath        = hc->batteryHealthPath.string();
+    config.batteryPresentPath       = hc->batteryPresentPath.string();
+    config.batteryCapacityPath      = hc->batteryCapacityPath.string();
+    config.batteryVoltagePath       = hc->batteryVoltagePath.string();
+    config.batteryTemperaturePath   = hc->batteryTemperaturePath.string();
+    config.batteryTechnologyPath    = hc->batteryTechnologyPath.string();
+    config.batteryCurrentNowPath    = hc->batteryCurrentNowPath.string();
+    config.batteryCurrentAvgPath    = hc->batteryCurrentAvgPath.string();
+    config.batteryChargeCounterPath = hc->batteryChargeCounterPath.string();
+    config.batteryFullChargePath    = hc->batteryFullChargePath.string();
+    config.batteryCycleCountPath    = hc->batteryCycleCountPath.string();
+
+}
+
+void convertFromHealthConfig(const HealthConfig& c, struct healthd_config *hc) {
+    hc->periodic_chores_interval_fast = c.periodicChoresIntervalFast;
+    hc->periodic_chores_interval_slow = c.periodicChoresIntervalSlow;
+
+    hc->batteryStatusPath =
+        android::String8(c.batteryStatusPath.c_str(),
+                         c.batteryStatusPath.size());
+
+    hc->batteryHealthPath =
+        android::String8(c.batteryHealthPath.c_str(),
+                         c.batteryHealthPath.size());
+
+    hc->batteryPresentPath =
+        android::String8(c.batteryPresentPath.c_str(),
+                         c.batteryPresentPath.size());
+
+    hc->batteryCapacityPath =
+        android::String8(c.batteryCapacityPath.c_str(),
+                         c.batteryCapacityPath.size());
+
+    hc->batteryVoltagePath =
+        android::String8(c.batteryVoltagePath.c_str(),
+                         c.batteryVoltagePath.size());
+
+    hc->batteryTemperaturePath =
+        android::String8(c.batteryTemperaturePath.c_str(),
+                         c.batteryTemperaturePath.size());
+
+    hc->batteryTechnologyPath =
+        android::String8(c.batteryTechnologyPath.c_str(),
+                         c.batteryTechnologyPath.size());
+
+    hc->batteryCurrentNowPath =
+        android::String8(c.batteryCurrentNowPath.c_str(),
+                         c.batteryCurrentNowPath.size());
+
+    hc->batteryCurrentAvgPath =
+        android::String8(c.batteryCurrentAvgPath.c_str(),
+                         c.batteryCurrentNowPath.size());
+
+    hc->batteryChargeCounterPath =
+        android::String8(c.batteryChargeCounterPath.c_str(),
+                         c.batteryChargeCounterPath.size());
+
+    hc->batteryFullChargePath =
+        android::String8(c.batteryFullChargePath.c_str(),
+                         c.batteryFullChargePath.size());
+
+    hc->batteryCycleCountPath =
+        android::String8(c.batteryCycleCountPath.c_str(),
+                         c.batteryCycleCountPath.size());
+
+    // energyCounter is handled through special means so all calls to
+    // the function go across the HALs
+
+    // boot_min_cap - never used in Android (only in charger-mode).
+
+    // screen_on - never used in Android (only in charger mode).
+}
+
+void convertToHealthInfo(const struct android::BatteryProperties *p,
+                                 HealthInfo& info) {
+    info.chargerAcOnline        = p->chargerAcOnline;
+    info.chargerUsbOnline       = p->chargerUsbOnline;
+    info.chargerWirelessOnline  = p->chargerWirelessOnline;
+    info.maxChargingCurrent     = p->maxChargingCurrent;
+    info.maxChargingVoltage     = p->maxChargingVoltage;
+    info.batteryStatus          = static_cast<BatteryStatus>(p->batteryStatus);
+    info.batteryHealth          = static_cast<BatteryHealth>(p->batteryHealth);
+    info.batteryPresent         = p->batteryPresent;
+    info.batteryLevel           = p->batteryLevel;
+    info.batteryVoltage         = p->batteryVoltage;
+    info.batteryTemperature     = p->batteryTemperature;
+    info.batteryCurrent         = p->batteryCurrent;
+    info.batteryCycleCount      = p->batteryCycleCount;
+    info.batteryFullCharge      = p->batteryFullCharge;
+    info.batteryChargeCounter   = p->batteryChargeCounter;
+    info.batteryTechnology      = p->batteryTechnology;
+}
+
+void convertFromHealthInfo(const HealthInfo& info,
+                                   struct android::BatteryProperties *p) {
+    p->chargerAcOnline          = info.chargerAcOnline;
+    p->chargerUsbOnline         = info.chargerUsbOnline;
+    p->chargerWirelessOnline    = info.chargerWirelessOnline;
+    p->maxChargingCurrent       = info.maxChargingCurrent;
+    p->maxChargingVoltage       = info.maxChargingVoltage;
+    p->batteryStatus            = static_cast<int>(info.batteryStatus);
+    p->batteryHealth            = static_cast<int>(info.batteryHealth);
+    p->batteryPresent           = info.batteryPresent;
+    p->batteryLevel             = info.batteryLevel;
+    p->batteryVoltage           = info.batteryVoltage;
+    p->batteryTemperature       = info.batteryTemperature;
+    p->batteryCurrent           = info.batteryCurrent;
+    p->batteryCycleCount        = info.batteryCycleCount;
+    p->batteryFullCharge        = info.batteryFullCharge;
+    p->batteryChargeCounter     = info.batteryChargeCounter;
+    p->batteryTechnology        = android::String8(info.batteryTechnology.c_str());
+}
+
+} // namespace hal_conversion
+} // namespace V1_0
+} // namespace health
+} // namespace hardware
+} // namespace android
diff --git a/health/1.0/default/include/hal_conversion.h b/health/1.0/default/include/hal_conversion.h
new file mode 100644
index 0000000..a92b208
--- /dev/null
+++ b/health/1.0/default/include/hal_conversion.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_HEALTH_V1_0_DEFAULT_INCLUDE_HAL_CONVERSION_H_
+#define HARDWARE_INTERFACES_HEALTH_V1_0_DEFAULT_INCLUDE_HAL_CONVERSION_H_
+
+#include <android/hardware/health/1.0/IHealth.h>
+#include <healthd/healthd.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V1_0 {
+namespace hal_conversion {
+
+void convertToHealthConfig(const struct healthd_config *hc,
+                            HealthConfig& config);
+void convertFromHealthConfig(const HealthConfig& c, struct healthd_config *hc);
+
+void convertToHealthInfo(const struct android::BatteryProperties *p,
+                                 HealthInfo& info);
+void convertFromHealthInfo(const HealthInfo& info,
+                                 struct android::BatteryProperties *p);
+
+}  // namespace hal_conversion
+}  // namespace V1_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_HEALTH_V1_0_DEFAULT_INCLUDE_HAL_CONVERSION_H_
diff --git a/health/1.0/default/libhealthd/Android.mk b/health/1.0/default/libhealthd/Android.mk
new file mode 100644
index 0000000..a5f4445
--- /dev/null
+++ b/health/1.0/default/libhealthd/Android.mk
@@ -0,0 +1,10 @@
+# Copyright 2016 The Android Open Source Project
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := healthd_board_default.cpp
+LOCAL_MODULE := libhealthd.default
+LOCAL_CFLAGS := -Werror
+LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
+include $(BUILD_STATIC_LIBRARY)
diff --git a/health/1.0/default/libhealthd/healthd_board_default.cpp b/health/1.0/default/libhealthd/healthd_board_default.cpp
new file mode 100644
index 0000000..127f98e
--- /dev/null
+++ b/health/1.0/default/libhealthd/healthd_board_default.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 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 <healthd/healthd.h>
+
+void healthd_board_init(struct healthd_config*)
+{
+    // use defaults
+}
+
+int healthd_board_battery_update(struct android::BatteryProperties*)
+{
+    // return 0 to log periodic polled battery status to kernel log
+    return 0;
+}
diff --git a/health/1.0/types.hal b/health/1.0/types.hal
new file mode 100644
index 0000000..c5b5cc1
--- /dev/null
+++ b/health/1.0/types.hal
@@ -0,0 +1,213 @@
+/*
+ * 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.
+ */
+
+package android.hardware.health@1.0;
+
+/*
+ * Possible return values for optional HAL method(s) like
+ * IHealth::energyCounter()
+ */
+enum Result : int32_t {
+    SUCCESS,
+    NOT_SUPPORTED,
+    UNKNOWN,
+};
+
+/*
+ * Possible values for Battery Status.
+ * Note: These are currently in sync with BatteryManager and must not
+ * be extended / altered.
+ */
+@export(name="", value_prefix="BATTERY_STATUS_")
+enum BatteryStatus : int32_t {
+    UNKNOWN = 1,
+    CHARGING = 2,
+    DISCHARGING = 3,
+    /*
+     * Battery is *not* charging - special case when charger is present
+     * but battery isn't charging
+     */
+    NOT_CHARGING = 4,
+    FULL = 5,
+};
+
+/*
+ * Possible values for Battery Health.
+ * Note: These are currently in sync with BatteryManager and must not
+ * be extended / altered.
+ */
+@export(name="", value_prefix="BATTERY_HEALTH_")
+enum BatteryHealth : int32_t {
+    UNKNOWN = 1,
+    GOOD = 2,
+    OVERHEAT = 3,
+    DEAD = 4,
+    OVER_VOLTAGE = 5,
+    /*
+     * Battery experienced an unknown/unspecifid failure.
+     */
+    UNSPECIFIED_FAILURE = 6,
+    COLD = 7,
+};
+
+struct HealthConfig {
+
+    /*
+     * periodicChoresIntervalFast is used while the device is not in
+     * suspend, or in suspend and connected to a charger (to watch for battery
+     * overheat due to charging)
+     */
+    int32_t periodicChoresIntervalFast;
+
+    /*
+     * periodicChoresIntervalSlow is used when the device is in suspend and
+     * not connected to a charger (to watch for a battery drained to zero
+     * remaining capacity).
+     */
+    int32_t periodicChoresIntervalSlow;
+
+    /*
+     * power_supply sysfs attribute file paths. Set these to specific paths
+     * to use for the associated battery parameters. Clients must search
+     * for appropriate power_supply attribute files to use, for any paths
+     * left empty after the HAL is initialized.
+     */
+
+    /*
+     * batteryStatusPath - file path to read battery charging status.
+     * (POWER_SUPPLY_PROP_STATUS)
+     */
+    string batteryStatusPath;
+
+
+    /*
+     * batteryHealthPath - file path to read battery health.
+     * (POWER_SUPPLY_PROP_HEALTH)
+     */
+    string batteryHealthPath;
+
+    /*
+     * batteryPresentPath - file path to read battery present status.
+     * (POWER_SUPPLY_PROP_PRESENT)
+     */
+    string batteryPresentPath;
+
+
+    /*
+     * batteryCapacityPath - file path to read remaining battery capacity.
+     * (POWER_SUPPLY_PROP_CAPACITY)
+     */
+    string batteryCapacityPath;
+
+    /*
+     * batteryVoltagePath - file path to read battery voltage.
+     * (POWER_SUPPLY_PROP_VOLTAGE_NOW)
+     */
+    string batteryVoltagePath;
+
+    /*
+     * batteryTemperaturePath - file path to read battery temperature in tenths
+     * of degree celcius. (POWER_SUPPLY_PROP_TEMP)
+     */
+    string batteryTemperaturePath;
+
+    /*
+     * batteryTechnologyPath - file path to read battery technology.
+     * (POWER_SUPPLY_PROP_TECHNOLOGY)
+     */
+    string batteryTechnologyPath;
+
+    /*
+     * batteryCurrentNowPath - file path to read battery instantaneous current.
+     * (POWER_SUPPLY_PROP_CURRENT_NOW)
+     */
+    string batteryCurrentNowPath;
+
+    /*
+     * batteryCurrentAvgPath - file path to read battery average current.
+     * (POWER_SUPPLY_PROP_CURRENT_AVG)
+     */
+    string batteryCurrentAvgPath;
+
+    /*
+     * batteryChargeCounterPath - file path to read battery accumulated charge.
+     * (POWER_SUPPLY_PROP_CHARGE_COUNTER)
+     */
+    string batteryChargeCounterPath;
+
+    /*
+     * batteryFullChargerPath - file path to read battery charge value when it
+     * is considered to be full. (POWER_SUPPLY_PROP_CHARGE_FULL)
+     */
+    string batteryFullChargePath;
+
+    /*
+     * batteryCycleCountPath - file path to read battery charge cycle count.
+     * (POWER_SUPPLY_PROP_CYCLE_COUNT)
+     */
+    string batteryCycleCountPath;
+};
+
+/*
+ * The parameter to healthd mainloop update calls
+ */
+struct HealthInfo {
+    /* AC charger state - 'true' if online */
+    bool chargerAcOnline;
+
+    /* USB charger state - 'true' if online */
+    bool chargerUsbOnline;
+
+    /* Wireless charger state - 'true' if online */
+    bool chargerWirelessOnline;
+
+    /* Maximum charging current supported by charger in uA */
+    int32_t maxChargingCurrent;
+
+    /* Maximum charging voltage supported by charger in uV */
+    int32_t maxChargingVoltage;
+
+    BatteryStatus batteryStatus;
+
+    BatteryHealth batteryHealth;
+
+    /* 'true' if battery is present */
+    bool batteryPresent;
+
+    /* Remaining battery capacity in percent */
+    int32_t batteryLevel;
+
+    /* Instantaneous battery voltage in uV */
+    int32_t batteryVoltage;
+
+    /* Instantaneous battery temperature in tenths of degree celcius */
+    int32_t batteryTemperature;
+
+    /* Instantaneous battery current in uA */
+    int32_t batteryCurrent;
+
+    /* Battery charge cycle count */
+    int32_t batteryCycleCount;
+
+    /* Battery charge value when it is considered to be "full" in uA-h */
+    int32_t batteryFullCharge;
+
+    /* Instantaneous battery capacity in uA-h */
+    int32_t batteryChargeCounter;
+
+    /* Battery technology, e.g. "Li-ion, Li-Poly" etc. */
+    string batteryTechnology;
+};
diff --git a/health/Android.bp b/health/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/health/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
new file mode 100644
index 0000000..a8247e1
--- /dev/null
+++ b/keymaster/3.0/Android.bp
@@ -0,0 +1,56 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.keymaster@3.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.keymaster@3.0",
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+    ],
+    out: [
+        "android/hardware/keymaster/3.0/types.cpp",
+        "android/hardware/keymaster/3.0/KeymasterDeviceAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.keymaster@3.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.keymaster@3.0",
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+    ],
+    out: [
+        "android/hardware/keymaster/3.0/types.h",
+        "android/hardware/keymaster/3.0/IKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/IHwKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BnHwKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BpHwKeymasterDevice.h",
+        "android/hardware/keymaster/3.0/BsKeymasterDevice.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.keymaster@3.0",
+    generated_sources: ["android.hardware.keymaster@3.0_genc++"],
+    generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/keymaster/3.0/IKeymasterDevice.hal b/keymaster/3.0/IKeymasterDevice.hal
new file mode 100644
index 0000000..50a41ec
--- /dev/null
+++ b/keymaster/3.0/IKeymasterDevice.hal
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ */
+
+package android.hardware.keymaster@3.0;
+
+/**
+ * Keymaster device definition.  For thorough documentation see the implementer's reference, at
+ * https://source.android.com/security/keystore/implementer-ref.html
+ */
+interface IKeymasterDevice {
+
+    /**
+     * Returns information about the underlying keymaster hardware.
+     *
+     * @return isSecure is true if keys are stored and never leave secure hardware (Trusted
+     *             Execution Environment or similar). CDD requires that all devices initially
+     *             launched with Marshmallow or later must have secure hardware.
+     *
+     * @return supportsEllipticCurve is true if the hardware supports Elliptic Curve cryptography
+     *             with the NIST curves (P-224, P-256, P-384, and P-521). CDD requires that all
+     *             devices initially launched with Nougat or later must support Elliptic Curve
+     *             cryptography.
+     *
+     * @return supportsSymmetricCryptography is true if the hardware supports symmetric
+     *             cryptography, including AES and HMAC. CDD requires that all devices initially
+     *             launched with Nougat or later must support hardware enforcement of Keymaster
+     *             authorizations.
+     *
+     * @return supportsAttestation is true if the hardware supports generation of Keymaster public
+     *             key attestation certificates, signed with a key injected in a secure
+     *             environment. CDD requires that all devices initially launched with Android O or
+     *             later must support hardware attestation.
+     */
+    getHardwareFeatures()
+        generates(bool isSecure, bool supportsEllipticCurve,
+                  bool supportsSymmetricCryptography, bool supportsAttestation);
+
+    /**
+     * Adds entropy to the RNG used by keymaster. Entropy added through this method is guaranteed
+     * not to be the only source of entropy used, and the mixing function is required to be secure,
+     * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
+     * predict (or control), then the RNG output is indistinguishable from random. Thus, if the
+     * entropy from any source is good, the output must be good.
+     *
+     * @param data Bytes to be mixed into the RNG.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    addRngEntropy(vec<uint8_t> data) generates(ErrorCode error);
+
+    /**
+     * Generates a key, or key pair, returning a key blob and/or a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
+     *             in params. See Tag in types.hal for the full list.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key, which generally contains a
+     *             copy of the key material, wrapped in a key unavailable outside secure hardware.
+     *
+     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristis in
+     *             types.hal.
+     */
+    generateKey(vec<KeyParameter> keyParams)
+        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Imports a key, or key pair, returning a key blob and/or a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as keymaster tag/value pairs, provided
+     *             in params.  See Tag for the full list.
+     *
+     * @param keyFormat The format of the key material to import. See KeyFormat in types.hal.
+     *
+     * @pram keyData The key material to import, in the format specifed in keyFormat.
+     *
+     * @return error See the ErrorCode enum.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key, which will generally
+     *             contain a copy of the key material, wrapped in a key unavailable outside secure
+     *             hardware.
+     *
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    importKey(vec<KeyParameter> params, KeyFormat keyFormat, vec<uint8_t> keyData)
+        generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
+     * must fully validate the integrity of the key).
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param clientId An opaque byte string identifying the client. This value must match the
+     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @param appData An opaque byte string provided by the application. This value must match the
+     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis in
+     *             types.hal.
+     */
+    getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
+        generates(ErrorCode error, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Exports a public key, returning the key in the specified format.
+     *
+     * @parm keyFormat The format used for export. See KeyFormat in types.hal.
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey().  The
+     *             referenced key must be asymmetric.
+     *
+     * @param clientId An opaque byte string identifying the client. This value must match the
+     *             Tag::APPLICATION_ID data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @param appData An opaque byte string provided by the application. This value must match the
+     *             Tag::APPLICATION_DATA data provided during key generation/import.  Without the
+     *             correct value it must be cryptographically impossible for the secure hardware to
+     *             obtain the key material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyMaterial The public key material in PKCS#8 format.
+     */
+    exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
+              vec<uint8_t> appData) generates(ErrorCode error, vec<uint8_t> keyMaterial);
+
+    /**
+     * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in
+     * keymaster. The certificate will contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and
+     * value defined in:
+     *
+     *     https://developer.android.com/training/articles/security-key-attestation.html.
+     *
+     * @param keyToAttest The opaque descriptor returned by generateKey() or importKey().  The
+     *             referenced key must be asymmetric.
+     *
+     * @param attestParams Parameters for the attestation, notably Tag::ATTESTATION_CHALLENGE.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
+        generates(ErrorCode error, vec<vec<uint8_t>> certChain);
+
+    /**
+     * Upgrades an old key. Keys can become "old" in two ways: Keymaster can be upgraded to a new
+     * version, or the system can be updated to invalidate the OS version and/or patch level. In
+     * either case, attempts to use an old key with getKeyCharacteristics(), exportKey(),
+     * attestKey() or begin() will result in keymaster returning
+     * ErrorCode::KEY_REQUIRES_UPGRADE. This method must then be called to upgrade the key.
+     *
+     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param upgradeParams A parameter list containing any parameters needed to complete the
+     *             upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    upgradeKey(vec<uint8_t> keyBlobToUpgrade, vec<KeyParameter> upgradeParams)
+        generates(ErrorCode error, vec<uint8_t> upgradedKeyBlob);
+
+    /**
+     * Deletes the key, or key pair, associated with the key blob. After calling this function it
+     * will be impossible to use the key for any other operations. May be applied to keys from
+     * foreign roots of trust (keys not usable under the current root of trust).
+     *
+     * This is a NOP for keys that don't have rollback protection.
+     *
+     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteKey(vec<uint8_t> keyBlob) generates(ErrorCode error);
+
+    /**
+     * Deletes all keys in the hardware keystore. Used when keystore is reset completely. After
+     * calling this function it will be impossible to use any previously generated or imported key
+     * blobs for any operations.
+     *
+     * This is a NOP if keys don't have rollback protection.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteAllKeys() generates(ErrorCode error);
+
+    /**
+     * Destroys knowledge of the device's ids. This prevents all device id attestation in the
+     * future. The destruction must be permanent so that not even a factory reset will restore the
+     * device ids.
+     *
+     * Device id attestation may be provided only if this method is fully implemented, allowing the
+     * user to permanently disable device id attestation. If this cannot be guaranteed, the device
+     * must never attest any device ids.
+     *
+     * This is a NOP if device id attestation is not supported.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    destroyAttestationIds() generates(ErrorCode error);
+
+    /**
+     * Begins a cryptographic operation using the specified key. If all is well, begin() will return
+     * ErrorCode::OK and create an operation handle which must be passed to subsequent calls to
+     * update(), finish() or abort().
+     *
+     * It is critical that each call to begin() be paired with a subsequent call to finish() or
+     * abort(), to allow the keymaster implementation to clean up any internal operation state.
+     * Failure to do this may leak internal state space or other internal resources and may
+     * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space
+     * for operations. Any result other than ErrorCode::OK from begin(), update() or finish()
+     * implicitly aborts the operation, in which case abort() need not be called (and will return
+     * ErrorCode::INVALID_OPERATION_HANDLE if called).
+     *
+     * @param purpose The purpose of the operation, one of KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT,
+     *             KeyPurpose::SIGN or KeyPurpose::VERIFY. Note that for AEAD modes, encryption and
+     *             decryption imply signing and verification, respectively, but must be specified as
+     *             KeyPurpose::ENCRYPT and KeyPurpose::DECRYPT.
+     *
+     * @param keyBlob The opaque key descriptor returned by generateKey() or importKey().  The key
+     *             must have a purpose compatible with purpose and all of its usage requirements
+     *             must be satisfied, or begin() will return an appropriate error code.
+     *
+     * @param inParams Additional parameters for the operation. This is typically used to provide
+     *             authentication data, with Tag::AUTH_TOKEN. If Tag::APPLICATION_ID or
+     *             Tag::APPLICATION_DATA were provided during generation, they must be provided
+     *             here, or the operation will fail with ErrorCode::INVALID_KEY_BLOB. For operations
+     *             that require a nonce or IV, on keys that were generated with Tag::CALLER_NONCE,
+     *             inParams may contain a tag Tag::NONCE.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Output parameters. Used to return additional data from the operation
+     *             initialization, notably to return the IV or nonce from operations that generate
+     *             an IV or nonce.
+     *
+     * @return operationHandle The newly-created operation handle which must be passed to update(),
+     *             finish() or abort().
+     */
+    begin(KeyPurpose purpose, vec<uint8_t> key, vec<KeyParameter> inParams)
+        generates(ErrorCode error, vec<KeyParameter> outParams, OperationHandle operationHandle);
+
+    /**
+     * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
+     * with begin().
+     *
+     * If operationHandle is invalid, update() will return ErrorCode::INVALID_OPERATION_HANDLE.
+     *
+     * update() may not consume all of the data provided in the data buffer. update() will return
+     * the amount consumed in inputConsumed. The caller may provide the unconsumed data in a
+     * subsequent call.
+     *
+     * @param operationHandle The operation handle returned by begin().
+     *
+     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+     *             specify Tag::ADDITIONAL_DATA. Note that additional data may be provided in
+     *             multiple calls to update(), but only until input data has been provided.
+     *
+     * @param input Data to be processed, per the parameters established in the call to begin().
+     *             Note that update() may or may not consume all of the data provided. See
+     *             inputConsumed.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return inputConsumed Amount of data that was consumed by update(). If this is less than the
+     *             amount provided, the caller may provide the remainder in a subsequent call to
+     *             update() or finish().
+     *
+     * @return outParams Output parameters, used to return additional data from the operation The
+     *             caller takes ownership of the output parameters array and must free it with
+     *             keymaster_free_param_set().
+     *
+     * @return output The output data, if any.
+     */
+    update(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input)
+        generates(ErrorCode error, uint32_t inputConsumed, vec<KeyParameter> outParams,
+                  vec<uint8_t> output);
+
+    /**
+     * Finalizes a cryptographic operation begun with begin() and invalidates operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin(). This handle will be
+     *             invalid when finish() returns.
+     *
+     * @param inParams Additional parameters for the operation. For AEAD modes, this is used to
+     *             specify Tag::ADDITIONAL_DATA, but only if no input data was provided to update().
+     *
+     * @param input Data to be processed, per the parameters established in the call to
+     *             begin(). finish() must consume all provided data or return
+     *             ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * @param signature The signature to be verified if the purpose specified in the begin() call
+     *             was KeyPurpose::VERIFY.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Any output parameters generated by finish().
+     *
+     * @return output The output data, if any.
+     */
+    finish(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input,
+           vec<uint8_t> signature)
+        generates(ErrorCode error, vec<KeyParameter> outParams, vec<uint8_t> output);
+
+    /**
+     * Aborts a cryptographic operation begun with begin(), freeing all internal resources and
+     * invalidating operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin(). This handle will be
+     *             invalid when abort() returns.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    abort(OperationHandle operationHandle) generates(ErrorCode error);
+};
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
new file mode 100644
index 0000000..36d8890
--- /dev/null
+++ b/keymaster/3.0/default/Android.mk
@@ -0,0 +1,43 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.keymaster@3.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    KeymasterDevice.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libsoftkeymasterdevice \
+    libcrypto \
+    libkeymaster1 \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.keymaster@3.0
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.keymaster@3.0-service
+LOCAL_INIT_RC := android.hardware.keymaster@3.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.keymaster@3.0
+
+include $(BUILD_EXECUTABLE)
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
new file mode 100644
index 0000000..563ff84
--- /dev/null
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -0,0 +1,716 @@
+/*
+ **
+ ** 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 "android.hardware.keymaster@3.0-impl"
+
+#include "KeymasterDevice.h"
+
+#include <cutils/log.h>
+
+#include <hardware/keymaster_defs.h>
+#include <keymaster/keymaster_configuration.h>
+#include <keymaster/soft_keymaster_device.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V3_0 {
+namespace implementation {
+
+using ::keymaster::SoftKeymasterDevice;
+
+class SoftwareOnlyHidlKeymasterEnforcement : public ::keymaster::KeymasterEnforcement {
+  public:
+    SoftwareOnlyHidlKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
+
+    uint32_t get_current_time() const override {
+        struct timespec tp;
+        int err = clock_gettime(CLOCK_MONOTONIC, &tp);
+        if (err || tp.tv_sec < 0) return 0;
+        return static_cast<uint32_t>(tp.tv_sec);
+    }
+
+    bool activation_date_valid(uint64_t) const override { return true; }
+    bool expiration_date_passed(uint64_t) const override { return false; }
+    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const override { return false; }
+    bool ValidateTokenSignature(const hw_auth_token_t&) const override { return true; }
+};
+
+class SoftwareOnlyHidlKeymasterContext : public ::keymaster::SoftKeymasterContext {
+  public:
+    SoftwareOnlyHidlKeymasterContext() : enforcement_(new SoftwareOnlyHidlKeymasterEnforcement) {}
+
+    ::keymaster::KeymasterEnforcement* enforcement_policy() override { return enforcement_.get(); }
+
+  private:
+    std::unique_ptr<::keymaster::KeymasterEnforcement> enforcement_;
+};
+
+static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster0_device_t* km0_device = NULL;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster0_open(mod, &km0_device);
+    if (rc) {
+        ALOGE("Error opening keystore keymaster0 device.");
+        goto err;
+    }
+
+    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
+        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
+        km0_device->common.close(&km0_device->common);
+        km0_device = NULL;
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = soft_keymaster.release()->keymaster2_device();
+        return 0;
+    }
+
+    ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km0_device);
+    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by  keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km0_device) km0_device->common.close(&km0_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
+    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
+
+    UniquePtr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
+    keymaster1_device_t* km1_device = nullptr;
+    keymaster_error_t error = KM_ERROR_OK;
+
+    int rc = keymaster1_open(mod, &km1_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster1 device", rc);
+        goto err;
+    }
+
+    ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
+    error = soft_keymaster->SetHardwareDevice(km1_device);
+    km1_device = nullptr;  // SoftKeymasterDevice has taken ownership.
+    if (error != KM_ERROR_OK) {
+        ALOGE("Got error %d from SetHardwareDevice", error);
+        rc = error;
+        goto err;
+    }
+
+    // SoftKeymasterDevice will be deleted by keymaster_device_release()
+    *dev = soft_keymaster.release()->keymaster2_device();
+    return 0;
+
+err:
+    if (km1_device) km1_device->common.close(&km1_device->common);
+    *dev = NULL;
+    return rc;
+}
+
+static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
+    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
+    ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
+
+    keymaster2_device_t* km2_device = nullptr;
+
+    int rc = keymaster2_open(mod, &km2_device);
+    if (rc) {
+        ALOGE("Error %d opening keystore keymaster2 device", rc);
+        goto err;
+    }
+
+    *dev = km2_device;
+    return 0;
+
+err:
+    if (km2_device) km2_device->common.close(&km2_device->common);
+    *dev = nullptr;
+    return rc;
+}
+
+static int keymaster_device_initialize(keymaster2_device_t** dev, uint32_t* version,
+                                       bool* supports_ec) {
+    const hw_module_t* mod;
+
+    *supports_ec = true;
+
+    int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
+    if (rc) {
+        ALOGI("Could not find any keystore module, using software-only implementation.");
+        // SoftKeymasterDevice will be deleted by keymaster_device_release()
+        *dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
+        *version = -1;
+        return 0;
+    }
+
+    if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
+        *version = 0;
+        int rc = keymaster0_device_initialize(mod, dev);
+        if (rc == 0 && ((*dev)->flags & KEYMASTER_SUPPORTS_EC) == 0) {
+            *supports_ec = false;
+        }
+        return rc;
+    } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
+        *version = 1;
+        return keymaster1_device_initialize(mod, dev);
+    } else {
+        *version = 2;
+        return keymaster2_device_initialize(mod, dev);
+    }
+}
+
+KeymasterDevice::~KeymasterDevice() {
+    if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
+}
+
+static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
+    return keymaster_tag_get_type(tag);
+}
+
+/**
+ * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
+ * cast to make the compiler happy. One of two thigs should happen though:
+ * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
+ *      single point of truth. Then this cast function can go away.
+ */
+inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
+    return keymaster_tag_t(value);
+}
+inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
+    return Tag(value);
+}
+inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
+    return keymaster_purpose_t(value);
+}
+inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
+    return keymaster_key_format_t(value);
+}
+inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
+    return ErrorCode(value);
+}
+
+class KmParamSet : public keymaster_key_param_set_t {
+  public:
+    KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
+        params = new keymaster_key_param_t[keyParams.size()];
+        length = keyParams.size();
+        for (size_t i = 0; i < keyParams.size(); ++i) {
+            auto tag = legacy_enum_conversion(keyParams[i].tag);
+            switch (typeFromTag(tag)) {
+            case KM_ENUM:
+            case KM_ENUM_REP:
+                params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
+                break;
+            case KM_UINT:
+            case KM_UINT_REP:
+                params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
+                break;
+            case KM_ULONG:
+            case KM_ULONG_REP:
+                params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
+                break;
+            case KM_DATE:
+                params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
+                break;
+            case KM_BOOL:
+                if (keyParams[i].f.boolValue)
+                    params[i] = keymaster_param_bool(tag);
+                else
+                    params[i].tag = KM_TAG_INVALID;
+                break;
+            case KM_BIGNUM:
+            case KM_BYTES:
+                params[i] =
+                    keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
+                break;
+            case KM_INVALID:
+            default:
+                params[i].tag = KM_TAG_INVALID;
+                /* just skip */
+                break;
+            }
+        }
+    }
+    KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
+        other.length = 0;
+        other.params = nullptr;
+    }
+    KmParamSet(const KmParamSet&) = delete;
+    ~KmParamSet() { delete[] params; }
+};
+
+inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
+    return KmParamSet(params);
+}
+
+inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {nullptr, 0};
+}
+
+inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
+    /* hidl unmarshals funny pointers if the the blob is empty */
+    if (blob.size()) return {&blob[0], blob.size()};
+    return {nullptr, 0};
+}
+
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
+    return result;
+}
+inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
+    hidl_vec<uint8_t> result;
+    result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
+    return result;
+}
+
+inline static hidl_vec<hidl_vec<uint8_t>>
+kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
+    hidl_vec<hidl_vec<uint8_t>> result;
+    if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
+
+    result.resize(cert_chain->entry_count);
+    for (size_t i = 0; i < cert_chain->entry_count; ++i) {
+        auto& entry = cert_chain->entries[i];
+        result[i] = kmBlob2hidlVec(entry);
+    }
+
+    return result;
+}
+
+static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
+    hidl_vec<KeyParameter> result;
+    if (set.length == 0 || set.params == nullptr) return result;
+
+    result.resize(set.length);
+    keymaster_key_param_t* params = set.params;
+    for (size_t i = 0; i < set.length; ++i) {
+        auto tag = params[i].tag;
+        result[i].tag = legacy_enum_conversion(tag);
+        switch (typeFromTag(tag)) {
+        case KM_ENUM:
+        case KM_ENUM_REP:
+            result[i].f.integer = params[i].enumerated;
+            break;
+        case KM_UINT:
+        case KM_UINT_REP:
+            result[i].f.integer = params[i].integer;
+            break;
+        case KM_ULONG:
+        case KM_ULONG_REP:
+            result[i].f.longInteger = params[i].long_integer;
+            break;
+        case KM_DATE:
+            result[i].f.dateTime = params[i].date_time;
+            break;
+        case KM_BOOL:
+            result[i].f.boolValue = params[i].boolean;
+            break;
+        case KM_BIGNUM:
+        case KM_BYTES:
+            result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
+                                         params[i].blob.data_length);
+            break;
+        case KM_INVALID:
+        default:
+            params[i].tag = KM_TAG_INVALID;
+            /* just skip */
+            break;
+        }
+    }
+    return result;
+}
+
+// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+Return<void> KeymasterDevice::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
+    bool is_secure = false;
+    bool supports_symmetric_cryptography = false;
+    bool supports_attestation = false;
+
+    switch (hardware_version_) {
+    case 2:
+        supports_attestation = true;
+    /* Falls through */
+    case 1:
+        supports_symmetric_cryptography = true;
+    /* Falls through */
+    case 0:
+        is_secure = true;
+        break;
+    };
+
+    _hidl_cb(is_secure, hardware_supports_ec_, supports_symmetric_cryptography,
+             supports_attestation);
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::addRngEntropy(const hidl_vec<uint8_t>& data) {
+    return legacy_enum_conversion(
+        keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
+}
+
+Return<void> KeymasterDevice::generateKey(const hidl_vec<KeyParameter>& keyParams,
+                                          generateKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    // convert the parameter set to something our backend understands
+    auto kmParams = hidlParams2KmParamSet(keyParams);
+
+    auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
+                                              &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    // send results off to the client
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                                    const hidl_vec<uint8_t>& clientId,
+                                                    const hidl_vec<uint8_t>& appData,
+                                                    getKeyCharacteristics_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+
+    // result variables the backend understands
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->get_key_characteristics(
+        keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
+        clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
+        &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
+
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                                        const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
+    // result variables for the wire
+    KeyCharacteristics resultCharacteristics;
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
+
+    auto kmParams = hidlParams2KmParamSet(params);
+    auto kmKeyData = hidlVec2KmBlob(keyData);
+
+    auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
+                                            legacy_enum_conversion(keyFormat), &kmKeyData,
+                                            &key_blob, &key_characteristics);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
+        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
+
+    // free buffers that we are responsible for
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+    keymaster_free_characteristics(&key_characteristics);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                                        const hidl_vec<uint8_t>& clientId,
+                                        const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    auto kmClientId = hidlVec2KmBlob(clientId);
+    auto kmAppData = hidlVec2KmBlob(appData);
+
+    auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
+                                            keyBlob.size() ? &kmKeyBlob : nullptr,
+                                            clientId.size() ? &kmClientId : nullptr,
+                                            appData.size() ? &kmAppData : nullptr, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
+        resultKeyBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    // free buffers that we are responsible for
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                                        const hidl_vec<KeyParameter>& attestParams,
+                                        attestKey_cb _hidl_cb) {
+
+    hidl_vec<hidl_vec<uint8_t>> resultCertChain;
+
+    for (size_t i = 0; i < attestParams.size(); ++i) {
+        switch (attestParams[i].tag) {
+            case Tag::ATTESTATION_ID_BRAND:
+            case Tag::ATTESTATION_ID_DEVICE:
+            case Tag::ATTESTATION_ID_PRODUCT:
+            case Tag::ATTESTATION_ID_SERIAL:
+            case Tag::ATTESTATION_ID_IMEI:
+            case Tag::ATTESTATION_ID_MEID:
+                // Device id attestation may only be supported if the device is able to permanently
+                // destroy its knowledge of the ids. This device is unable to do this, so it must
+                // never perform any device id attestation.
+                _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
+                return Void();
+            default:
+                break;
+        }
+    }
+
+    keymaster_cert_chain_t cert_chain{nullptr, 0};
+
+    auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
+    auto kmAttestParams = hidlParams2KmParamSet(attestParams);
+
+    auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
+                                            &cert_chain);
+
+    if (rc == KM_ERROR_OK) {
+        resultCertChain = kmCertChain2Hidl(&cert_chain);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
+
+    keymaster_free_cert_chain(&cert_chain);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                                         const hidl_vec<KeyParameter>& upgradeParams,
+                                         upgradeKey_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<uint8_t> resultKeyBlob;
+
+    // result variables the backend understands
+    keymaster_key_blob_t key_blob{nullptr, 0};
+
+    auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
+    auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
+
+    auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
+                                             &kmUpgradeParams, &key_blob);
+
+    if (rc == KM_ERROR_OK) {
+        // on success convert the result to wire format
+        resultKeyBlob = kmBlob2hidlVec(key_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
+
+    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
+
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
+    return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
+}
+
+Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
+    if (keymaster_device_->delete_all_keys == nullptr) {
+        return ErrorCode::UNIMPLEMENTED;
+    }
+    return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
+}
+
+Return<ErrorCode> KeymasterDevice::destroyAttestationIds() {
+    return ErrorCode::UNIMPLEMENTED;
+}
+
+Return<void> KeymasterDevice::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                                    const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
+
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    uint64_t resultOpHandle = 0;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_operation_handle_t& operation_handle = resultOpHandle;
+
+    auto kmKey = hidlVec2KmKeyBlob(key);
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+
+    auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
+                                       &kmInParams, &out_params, &operation_handle);
+
+    if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
+
+    keymaster_free_param_set(&out_params);
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::update(uint64_t operationHandle,
+                                     const hidl_vec<KeyParameter>& inParams,
+                                     const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
+    // result variables for the wire
+    uint32_t resultConsumed = 0;
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    size_t consumed = 0;
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+
+    auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &consumed, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultConsumed = consumed;
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<void> KeymasterDevice::finish(uint64_t operationHandle,
+                                     const hidl_vec<KeyParameter>& inParams,
+                                     const hidl_vec<uint8_t>& input,
+                                     const hidl_vec<uint8_t>& signature, finish_cb _hidl_cb) {
+    // result variables for the wire
+    hidl_vec<KeyParameter> resultParams;
+    hidl_vec<uint8_t> resultBlob;
+
+    // result variables the backend understands
+    keymaster_key_param_set_t out_params{nullptr, 0};
+    keymaster_blob_t out_blob{nullptr, 0};
+
+    auto kmInParams = hidlParams2KmParamSet(inParams);
+    auto kmInput = hidlVec2KmBlob(input);
+    auto kmSignature = hidlVec2KmBlob(signature);
+
+    auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
+                                        &kmSignature, &out_params, &out_blob);
+
+    if (rc == KM_ERROR_OK) {
+        resultParams = kmParamSet2Hidl(out_params);
+        resultBlob = kmBlob2hidlVec(out_blob);
+    }
+
+    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
+
+    keymaster_free_param_set(&out_params);
+    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
+
+    return Void();
+}
+
+Return<ErrorCode> KeymasterDevice::abort(uint64_t operationHandle) {
+    return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
+}
+
+IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* /* name */) {
+    keymaster2_device_t* dev = nullptr;
+
+    uint32_t version;
+    bool supports_ec;
+    auto rc = keymaster_device_initialize(&dev, &version, &supports_ec);
+    if (rc) return nullptr;
+
+    auto kmrc = ::keymaster::ConfigureDevice(dev);
+    if (kmrc != KM_ERROR_OK) {
+        dev->common.close(&dev->common);
+        return nullptr;
+    }
+
+    return new KeymasterDevice(dev, version, supports_ec);
+}
+
+}  // namespace implementation
+}  // namespace V3_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/3.0/default/KeymasterDevice.h b/keymaster/3.0/default/KeymasterDevice.h
new file mode 100644
index 0000000..382f45f
--- /dev/null
+++ b/keymaster/3.0/default/KeymasterDevice.h
@@ -0,0 +1,98 @@
+/*
+ **
+ ** 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 HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
+#define HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
+
+#include <hardware/keymaster2.h>
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V3_0 {
+namespace implementation {
+
+using ::android::hardware::keymaster::V3_0::ErrorCode;
+using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
+using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::KeyParameter;
+using ::android::hardware::keymaster::V3_0::KeyPurpose;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+class KeymasterDevice : public IKeymasterDevice {
+  public:
+    KeymasterDevice(keymaster2_device_t* dev, uint32_t hardware_version, bool hardware_supports_ec)
+        : keymaster_device_(dev), hardware_version_(hardware_version),
+          hardware_supports_ec_(hardware_supports_ec) {}
+    virtual ~KeymasterDevice();
+
+    // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
+    Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
+    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override;
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override;
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override;
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override;
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override;
+    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<ErrorCode> deleteAllKeys() override;
+    Return<ErrorCode> destroyAttestationIds() override;
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        finish_cb _hidl_cb) override;
+    Return<ErrorCode> abort(uint64_t operationHandle) override;
+
+  private:
+    keymaster2_device_t* keymaster_device_;
+    uint32_t hardware_version_;
+    bool hardware_supports_ec_;
+};
+
+extern "C" IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* name);
+
+}  // namespace implementation
+}  // namespace V3_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
new file mode 100644
index 0000000..86ed1e7
--- /dev/null
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -0,0 +1,4 @@
+service keymaster-3-0 /system/bin/hw/android.hardware.keymaster@3.0-service
+    class hal
+    user system
+    group system drmrpc
diff --git a/keymaster/3.0/default/service.cpp b/keymaster/3.0/default/service.cpp
new file mode 100644
index 0000000..dd8c0b2
--- /dev/null
+++ b/keymaster/3.0/default/service.cpp
@@ -0,0 +1,35 @@
+/*
+**
+** 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 "android.hardware.keymaster@3.0-service"
+
+#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+using android::hardware::keymaster::V3_0::IKeymasterDevice;
+using android::hardware::registerPassthroughServiceImplementation;
+
+int main() {
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+    registerPassthroughServiceImplementation<IKeymasterDevice>("keymaster");
+    joinRpcThreadpool();
+}
diff --git a/keymaster/3.0/types.hal b/keymaster/3.0/types.hal
new file mode 100644
index 0000000..9f29b6a
--- /dev/null
+++ b/keymaster/3.0/types.hal
@@ -0,0 +1,429 @@
+/*
+ * 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.
+ */
+
+package android.hardware.keymaster@3.0;
+
+enum TagType : uint32_t {
+    INVALID = 0 << 28, /* Invalid type, used to designate a tag as uninitialized */
+    ENUM = 1 << 28,
+    ENUM_REP = 2 << 28, /* Repeatable enumeration value. */
+    UINT = 3 << 28,
+    UINT_REP = 4 << 28, /* Repeatable integer value */
+    ULONG = 5 << 28,
+    DATE = 6 << 28,
+    BOOL = 7 << 28,
+    BIGNUM = 8 << 28,
+    BYTES = 9 << 28,
+    ULONG_REP = 10 << 28, /* Repeatable long value */
+};
+
+enum Tag : uint32_t {
+    INVALID = TagType:INVALID | 0,
+
+    /*
+     * Tags that must be semantically enforced by hardware and software implementations.
+     */
+
+    /* Crypto parameters */
+    PURPOSE = TagType:ENUM_REP | 1,    /* KeyPurpose. */
+    ALGORITHM = TagType:ENUM | 2,      /* Algorithm. */
+    KEY_SIZE = TagType:UINT | 3,       /* Key size in bits. */
+    BLOCK_MODE = TagType:ENUM_REP | 4, /* BlockMode. */
+    DIGEST = TagType:ENUM_REP | 5,     /* Digest. */
+    PADDING = TagType:ENUM_REP | 6,    /* PaddingMode. */
+    CALLER_NONCE = TagType:BOOL | 7,   /* Allow caller to specify nonce or IV. */
+    MIN_MAC_LENGTH = TagType:UINT | 8, /* Minimum length of MAC or AEAD authentication tag in
+                                        * bits. */
+    KDF = TagType:ENUM_REP | 9,        /* KeyDerivationFunction. */
+    EC_CURVE = TagType:ENUM | 10,      /* EcCurve. */
+
+    /* Algorithm-specific. */
+    RSA_PUBLIC_EXPONENT = TagType:ULONG | 200,
+    ECIES_SINGLE_HASH_MODE = TagType:BOOL | 201, /* Whether the ephemeral public key is fed into the
+                                                  * KDF. */
+    INCLUDE_UNIQUE_ID = TagType:BOOL | 202,      /* If true, attestation certificates for this key
+                                                  * will contain an application-scoped and
+                                                  * time-bounded device-unique ID.*/
+
+    /* Other hardware-enforced. */
+    BLOB_USAGE_REQUIREMENTS = TagType:ENUM | 301, /* KeyBlobUsageRequirements. */
+    BOOTLOADER_ONLY = TagType:BOOL | 302,         /* Usable only by bootloader. */
+
+    /*
+     * Tags that should be semantically enforced by hardware if possible and will otherwise be
+     * enforced by software (keystore).
+     */
+
+    /* Key validity period */
+    ACTIVE_DATETIME = TagType:DATE | 400,             /* Start of validity. */
+    ORIGINATION_EXPIRE_DATETIME = TagType:DATE | 401, /* Date when new "messages" should no longer
+                                                       * be created. */
+    USAGE_EXPIRE_DATETIME = TagType:DATE | 402,       /* Date when existing "messages" should no
+                                                       * longer be trusted. */
+    MIN_SECONDS_BETWEEN_OPS = TagType:UINT | 403,     /* Minimum elapsed time between
+                                                       * cryptographic operations with the key. */
+    MAX_USES_PER_BOOT = TagType:UINT | 404,           /* Number of times the key can be used per
+                                                       * boot. */
+
+    /* User authentication */
+    ALL_USERS = TagType:BOOL | 500,           /* Reserved for future use -- ignore. */
+    USER_ID = TagType:UINT | 501,             /* Reserved for future use -- ignore. */
+    USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
+                                               * Disallowed if ALL_USERS or NO_AUTH_REQUIRED is
+                                               * present. */
+    NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
+    USER_AUTH_TYPE = TagType:ENUM | 504,      /* Bitmask of authenticator types allowed when
+                                               * USER_SECURE_ID contains a secure user ID, rather
+                                               * than a secure authenticator ID.  Defined in
+                                               * HardwareAuthenticatorType. */
+    AUTH_TIMEOUT = TagType:UINT | 505,        /* Required freshness of user authentication for
+                                               * private/secret key operations, in seconds.  Public
+                                               * key operations require no authentication.  If
+                                               * absent, authentication is required for every use.
+                                               * Authentication state is lost when the device is
+                                               * powered off. */
+    ALLOW_WHILE_ON_BODY = TagType:BOOL | 506, /* Allow key to be used after authentication timeout
+                                               * if device is still on-body (requires secure on-body
+                                               * sensor. */
+
+    /* Application access control */
+    ALL_APPLICATIONS = TagType:BOOL | 600, /* Specified to indicate key is usable by all
+                                            * applications. */
+    APPLICATION_ID = TagType:BYTES | 601,  /* Byte string identifying the authorized application. */
+    EXPORTABLE = TagType:BOOL | 602,       /* If true, private/secret key can be exported, but only
+                                            * if all access control requirements for use are
+                                            * met. (keymaster2) */
+
+    /*
+     * Semantically unenforceable tags, either because they have no specific meaning or because
+     * they're informational only.
+     */
+    APPLICATION_DATA = TagType:BYTES | 700,      /* Data provided by authorized application. */
+    CREATION_DATETIME = TagType:DATE | 701,      /* Key creation time */
+    ORIGIN = TagType:ENUM | 702,                 /* keymaster_key_origin_t. */
+    ROLLBACK_RESISTANT = TagType:BOOL | 703,     /* Whether key is rollback-resistant. */
+    ROOT_OF_TRUST = TagType:BYTES | 704,         /* Root of trust ID. */
+    OS_VERSION = TagType:UINT | 705,             /* Version of system (keymaster2) */
+    OS_PATCHLEVEL = TagType:UINT | 706,          /* Patch level of system (keymaster2) */
+    UNIQUE_ID = TagType:BYTES | 707,             /* Used to provide unique ID in attestation */
+    ATTESTATION_CHALLENGE = TagType:BYTES | 708, /* Used to provide challenge in attestation */
+    ATTESTATION_APPLICATION_ID = TagType:BYTES | 709, /* Used to identify the set of possible
+                                                       * applications of which one has initiated a
+                                                       * key attestation */
+    ATTESTATION_ID_BRAND = TagType:BYTES | 710,  /* Used to provide the device's brand name to be
+                                                    included in attestation */
+    ATTESTATION_ID_DEVICE = TagType:BYTES | 711, /* Used to provide the device's device name to be
+                                                    included in attestation */
+    ATTESTATION_ID_PRODUCT = TagType:BYTES | 712, /* Used to provide the device's product name to be
+                                                     included in attestation */
+    ATTESTATION_ID_SERIAL = TagType:BYTES | 713, /* Used to provide the device's serial number to be
+                                                    included in attestation */
+    ATTESTATION_ID_IMEI = TagType:BYTES | 714,   /* Used to provide the device's IMEI to be included
+                                                    in attestation */
+    ATTESTATION_ID_MEID = TagType:BYTES | 715,   /* Used to provide the device's MEID to be included
+                                                    in attestation */
+
+
+    /* Tags used only to provide data to or receive data from operations */
+    ASSOCIATED_DATA = TagType:BYTES | 1000, /* Used to provide associated data for AEAD modes. */
+    NONCE = TagType:BYTES | 1001,           /* Nonce or Initialization Vector */
+    AUTH_TOKEN = TagType:BYTES | 1002,      /* Authentication token that proves secure user
+                                             * authentication has been performed.  Structure defined
+                                             * in hw_auth_token_t in hw_auth_token.h. */
+    MAC_LENGTH = TagType:UINT | 1003,       /* MAC or AEAD authentication tag length in bits. */
+
+    RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004, /* Whether the device has beeen factory reset
+                                                    * since the last unique ID rotation.  Used for
+                                                    * key attestation. */
+};
+
+enum Algorithm : uint32_t {
+    /* Asymmetric algorithms. */
+    RSA = 1,
+    // DSA = 2, -- Removed, do not re-use value 2.
+    EC = 3,
+
+    /* Block ciphers algorithms */
+    AES = 32,
+
+    /* MAC algorithms */
+    HMAC = 128,
+};
+
+/**
+ * Symmetric block cipher modes provided by keymaster implementations.
+ */
+enum BlockMode : uint32_t {
+    /* Unauthenticated modes, usable only for encryption/decryption and not generally recommended
+     * except for compatibility with existing other protocols. */
+    ECB = 1,
+    CBC = 2,
+    CTR = 3,
+
+    /* Authenticated modes, usable for encryption/decryption and signing/verification.  Recommended
+     * over unauthenticated modes for all purposes. */
+    GCM = 32,
+};
+
+/**
+ * Padding modes that may be applied to plaintext for encryption operations.  This list includes
+ * padding modes for both symmetric and asymmetric algorithms.  Note that implementations should not
+ * provide all possible combinations of algorithm and padding, only the
+ * cryptographically-appropriate pairs.
+ */
+enum PaddingMode : uint32_t {
+    NONE = 1, /* deprecated */
+    RSA_OAEP = 2,
+    RSA_PSS = 3,
+    RSA_PKCS1_1_5_ENCRYPT = 4,
+    RSA_PKCS1_1_5_SIGN = 5,
+    PKCS7 = 64,
+};
+
+/**
+ * Digests provided by keymaster implementations.
+ */
+enum Digest : uint32_t {
+    NONE = 0,
+    MD5 = 1, /* Optional, may not be implemented in hardware, will be handled in software if
+              * needed. */
+    SHA1 = 2,
+    SHA_2_224 = 3,
+    SHA_2_256 = 4,
+    SHA_2_384 = 5,
+    SHA_2_512 = 6,
+};
+
+/**
+ * Supported EC curves, used in ECDSA
+ */
+enum EcCurve : uint32_t {
+    P_224 = 0,
+    P_256 = 1,
+    P_384 = 2,
+    P_521 = 3,
+};
+
+/**
+ * The origin of a key (or pair), i.e. where it was generated.  Note that ORIGIN can be found in
+ * either the hardware-enforced or software-enforced list for a key, indicating whether the key is
+ * hardware or software-based.  Specifically, a key with GENERATED in the hardware-enforced list is
+ * guaranteed never to have existed outide the secure hardware.
+ */
+enum KeyOrigin : uint32_t {
+    GENERATED = 0, /* Generated in keymaster.  Should not exist outside the TEE. */
+    DERIVED = 1,   /* Derived inside keymaster.  Likely exists off-device. */
+    IMPORTED = 2,  /* Imported into keymaster.  Existed as cleartext in Android. */
+    UNKNOWN = 3,   /* Keymaster did not record origin.  This value can only be seen on keys in a
+                    * keymaster0 implementation.  The keymaster0 adapter uses this value to document
+                    * the fact that it is unkown whether the key was generated inside or imported
+                    * into keymaster. */
+};
+
+/**
+ * Usability requirements of key blobs.  This defines what system functionality must be available
+ * for the key to function.  For example, key "blobs" which are actually handles referencing
+ * encrypted key material stored in the file system cannot be used until the file system is
+ * available, and should have BLOB_REQUIRES_FILE_SYSTEM.  Other requirements entries will be added
+ * as needed for implementations.
+ */
+enum KeyBlobUsageRequirements : uint32_t {
+    STANDALONE = 0,
+    REQUIRES_FILE_SYSTEM = 1,
+};
+
+/**
+ * Possible purposes of a key (or pair).
+ */
+enum KeyPurpose : uint32_t {
+    ENCRYPT = 0,    /* Usable with RSA, EC and AES keys. */
+    DECRYPT = 1,    /* Usable with RSA, EC and AES keys. */
+    SIGN = 2,       /* Usable with RSA, EC and HMAC keys. */
+    VERIFY = 3,     /* Usable with RSA, EC and HMAC keys. */
+    DERIVE_KEY = 4, /* Usable with EC keys. */
+    WRAP_KEY = 5,   /* Usable with wrapping keys. */
+};
+
+/**
+ * Keymaster error codes.
+ */
+enum ErrorCode : uint32_t {
+    OK = 0,
+    ROOT_OF_TRUST_ALREADY_SET = -1,
+    UNSUPPORTED_PURPOSE = -2,
+    INCOMPATIBLE_PURPOSE = -3,
+    UNSUPPORTED_ALGORITHM = -4,
+    INCOMPATIBLE_ALGORITHM = -5,
+    UNSUPPORTED_KEY_SIZE = -6,
+    UNSUPPORTED_BLOCK_MODE = -7,
+    INCOMPATIBLE_BLOCK_MODE = -8,
+    UNSUPPORTED_MAC_LENGTH = -9,
+    UNSUPPORTED_PADDING_MODE = -10,
+    INCOMPATIBLE_PADDING_MODE = -11,
+    UNSUPPORTED_DIGEST = -12,
+    INCOMPATIBLE_DIGEST = -13,
+    INVALID_EXPIRATION_TIME = -14,
+    INVALID_USER_ID = -15,
+    INVALID_AUTHORIZATION_TIMEOUT = -16,
+    UNSUPPORTED_KEY_FORMAT = -17,
+    INCOMPATIBLE_KEY_FORMAT = -18,
+    UNSUPPORTED_KEY_ENCRYPTION_ALGORITHM = -19,   /* For PKCS8 & PKCS12 */
+    UNSUPPORTED_KEY_VERIFICATION_ALGORITHM = -20, /* For PKCS8 & PKCS12 */
+    INVALID_INPUT_LENGTH = -21,
+    KEY_EXPORT_OPTIONS_INVALID = -22,
+    DELEGATION_NOT_ALLOWED = -23,
+    KEY_NOT_YET_VALID = -24,
+    KEY_EXPIRED = -25,
+    KEY_USER_NOT_AUTHENTICATED = -26,
+    OUTPUT_PARAMETER_NULL = -27,
+    INVALID_OPERATION_HANDLE = -28,
+    INSUFFICIENT_BUFFER_SPACE = -29,
+    VERIFICATION_FAILED = -30,
+    TOO_MANY_OPERATIONS = -31,
+    UNEXPECTED_NULL_POINTER = -32,
+    INVALID_KEY_BLOB = -33,
+    IMPORTED_KEY_NOT_ENCRYPTED = -34,
+    IMPORTED_KEY_DECRYPTION_FAILED = -35,
+    IMPORTED_KEY_NOT_SIGNED = -36,
+    IMPORTED_KEY_VERIFICATION_FAILED = -37,
+    INVALID_ARGUMENT = -38,
+    UNSUPPORTED_TAG = -39,
+    INVALID_TAG = -40,
+    MEMORY_ALLOCATION_FAILED = -41,
+    IMPORT_PARAMETER_MISMATCH = -44,
+    SECURE_HW_ACCESS_DENIED = -45,
+    OPERATION_CANCELLED = -46,
+    CONCURRENT_ACCESS_CONFLICT = -47,
+    SECURE_HW_BUSY = -48,
+    SECURE_HW_COMMUNICATION_FAILED = -49,
+    UNSUPPORTED_EC_FIELD = -50,
+    MISSING_NONCE = -51,
+    INVALID_NONCE = -52,
+    MISSING_MAC_LENGTH = -53,
+    KEY_RATE_LIMIT_EXCEEDED = -54,
+    CALLER_NONCE_PROHIBITED = -55,
+    KEY_MAX_OPS_EXCEEDED = -56,
+    INVALID_MAC_LENGTH = -57,
+    MISSING_MIN_MAC_LENGTH = -58,
+    UNSUPPORTED_MIN_MAC_LENGTH = -59,
+    UNSUPPORTED_KDF = -60,
+    UNSUPPORTED_EC_CURVE = -61,
+    KEY_REQUIRES_UPGRADE = -62,
+    ATTESTATION_CHALLENGE_MISSING = -63,
+    KEYMASTER_NOT_CONFIGURED = -64,
+    ATTESTATION_APPLICATION_ID_MISSING = -65,
+    CANNOT_ATTEST_IDS = -66,
+
+    UNIMPLEMENTED = -100,
+    VERSION_MISMATCH = -101,
+
+    UNKNOWN_ERROR = -1000,
+};
+
+/**
+ * Key derivation functions, mostly used in ECIES.
+ */
+enum KeyDerivationFunction : uint32_t {
+    /* Do not apply a key derivation function; use the raw agreed key */
+    NONE = 0,
+    /* HKDF defined in RFC 5869 with SHA256 */
+    RFC5869_SHA256 = 1,
+    /* KDF1 defined in ISO 18033-2 with SHA1 */
+    ISO18033_2_KDF1_SHA1 = 2,
+    /* KDF1 defined in ISO 18033-2 with SHA256 */
+    ISO18033_2_KDF1_SHA256 = 3,
+    /* KDF2 defined in ISO 18033-2 with SHA1 */
+    ISO18033_2_KDF2_SHA1 = 4,
+    /* KDF2 defined in ISO 18033-2 with SHA256 */
+    ISO18033_2_KDF2_SHA256 = 5,
+};
+
+/**
+ * Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
+ * authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
+ * authenticating to activate a key.
+ */
+enum HardwareAuthenticatorType : uint32_t {
+    NONE = 0,
+    PASSWORD = 1 << 0,
+    FINGERPRINT = 1 << 1,
+    // Additional entries must be powers of 2.
+    ANY = 0xFFFFFFFF,
+};
+
+struct KeyParameter {
+    /* Discriminates the uinon/blob field used.  The blob cannot be coincided with the union, but
+     * only one of "f" and "blob" is ever used at a time. */
+    Tag tag;
+    union IntegerParams {
+        /* Enum types */
+        Algorithm algorithm;
+        BlockMode blockMode;
+        PaddingMode paddingMode;
+        Digest digest;
+        EcCurve ecCurve;
+        KeyOrigin origin;
+        KeyBlobUsageRequirements keyBlobUsageRequirements;
+        KeyPurpose purpose;
+        KeyDerivationFunction keyDerivationFunction;
+        HardwareAuthenticatorType hardwareAuthenticatorType;
+
+        /* Other types */
+        bool boolValue;  // Always true, if a boolean tag is present.
+        uint32_t integer;
+        uint64_t longInteger;
+        uint64_t dateTime;
+    };
+    IntegerParams f;  // Hidl does not support anonymous unions, so we have to name it.
+    vec<uint8_t> blob;
+};
+
+struct KeyCharacteristics {
+    vec<KeyParameter> softwareEnforced;
+    vec<KeyParameter> teeEnforced;
+};
+
+/**
+ * Data used to prove successful authentication.
+ */
+struct HardwareAuthToken {
+    uint64_t challenge;
+    uint64_t userId;             // Secure User ID, not Android user ID.
+    uint64_t authenticatorId;    // Secure authenticator ID.
+    uint32_t authenticatorType;  // HardwareAuthenticatorType, in network order.
+    uint64_t timestamp;          // In network order.
+    uint8_t[32] hmac;            // HMAC is computed over 0 || challenge || user_id ||
+                                 // authenticator_id || authenticator_type || timestamp, with a
+                                 // prefixed 0 byte (which was a version field in Keymaster1 and
+                                 // Keymaster2) and the fields packed (no padding; so you probably
+                                 // can't just compute over the bytes of the struct).
+};
+
+enum SecurityLevel : uint32_t {
+    SOFTWARE = 0,
+    TRUSTED_ENVIRONMENT = 1,
+};
+
+/**
+ * Formats for key import and export.
+ */
+enum KeyFormat : uint32_t {
+    X509 = 0,  /* for public key export */
+    PKCS8 = 1, /* for asymmetric key pair import */
+    RAW = 3,   /* for symmetric key import and export*/
+};
+
+typedef uint64_t OperationHandle;
diff --git a/keymaster/Android.bp b/keymaster/Android.bp
new file mode 100644
index 0000000..09b8cb2
--- /dev/null
+++ b/keymaster/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "3.0",
+]
diff --git a/light/2.0/Android.bp b/light/2.0/Android.bp
new file mode 100644
index 0000000..118be88
--- /dev/null
+++ b/light/2.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.light@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0",
+    srcs: [
+        "types.hal",
+        "ILight.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/types.cpp",
+        "android/hardware/light/2.0/LightAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.light@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0",
+    srcs: [
+        "types.hal",
+        "ILight.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/types.h",
+        "android/hardware/light/2.0/ILight.h",
+        "android/hardware/light/2.0/IHwLight.h",
+        "android/hardware/light/2.0/BnHwLight.h",
+        "android/hardware/light/2.0/BpHwLight.h",
+        "android/hardware/light/2.0/BsLight.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.light@2.0",
+    generated_sources: ["android.hardware.light@2.0_genc++"],
+    generated_headers: ["android.hardware.light@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.light@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.light.vts.driver@2.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/light/2.0/ $(genDir)/android/hardware/light/2.0/",
+    srcs: [
+        "types.hal",
+        "ILight.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/types.vts.cpp",
+        "android/hardware/light/2.0/Light.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.light.vts.driver@2.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/light/2.0/ $(genDir)/android/hardware/light/2.0/",
+    srcs: [
+        "types.hal",
+        "ILight.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/types.vts.h",
+        "android/hardware/light/2.0/Light.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.light.vts.driver@2.0",
+    generated_sources: ["android.hardware.light.vts.driver@2.0_genc++"],
+    generated_headers: ["android.hardware.light.vts.driver@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.light.vts.driver@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.light@2.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.light@2.0-ILight-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/light/2.0/ $(genDir)/android/hardware/light/2.0/",
+    srcs: [
+        "ILight.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/Light.vts.cpp",
+        "android/hardware/light/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.light@2.0-ILight-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.light@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/light/2.0/ $(genDir)/android/hardware/light/2.0/",
+    srcs: [
+        "ILight.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/light/2.0/Light.vts.h",
+        "android/hardware/light/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.light@2.0-ILight-vts.profiler",
+    generated_sources: ["android.hardware.light@2.0-ILight-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.light@2.0-ILight-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.light@2.0-ILight-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.light@2.0",
+    ],
+}
diff --git a/light/2.0/Android.mk b/light/2.0/Android.mk
new file mode 100644
index 0000000..ef19bad
--- /dev/null
+++ b/light/2.0/Android.mk
@@ -0,0 +1,270 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.light@2.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (Brightness)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Brightness.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Brightness
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Flash)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Flash.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Flash
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (LightState)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/LightState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.LightState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Type)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Type.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Type
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ILight.hal
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/ILight.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ILight.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::ILight
+
+$(GEN): $(LOCAL_PATH)/ILight.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.light@2.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (Brightness)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Brightness.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Brightness
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Flash)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Flash.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Flash
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (LightState)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/LightState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.LightState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Type)
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/Type.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::types.Type
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ILight.hal
+#
+GEN := $(intermediates)/android/hardware/light/V2_0/ILight.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/ILight.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.light@2.0::ILight
+
+$(GEN): $(LOCAL_PATH)/ILight.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/light/2.0/ILight.hal b/light/2.0/ILight.hal
new file mode 100644
index 0000000..a7cd684
--- /dev/null
+++ b/light/2.0/ILight.hal
@@ -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.
+ */
+
+package android.hardware.light@2.0;
+
+interface ILight {
+
+    /**
+     * Set the provided lights to the provided values.
+     *
+     * @param type logical light to set
+     * @param state describes what the light should look like.
+     * @return status result of applying state transformation.
+     */
+    setLight(Type type, LightState state) generates (Status status);
+
+    /**
+     * Discover what indicator lights are available.
+     *
+     * @return types list of available lights
+     */
+    getSupportedTypes() generates (vec<Type> types);
+
+};
diff --git a/light/2.0/default/Android.mk b/light/2.0/default/Android.mk
new file mode 100644
index 0000000..d14d7c0
--- /dev/null
+++ b/light/2.0/default/Android.mk
@@ -0,0 +1,45 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.light@2.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    Light.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    liblog \
+    libcutils \
+    libhardware \
+    libbase \
+    libcutils \
+    android.hardware.light@2.0 \
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.light@2.0-service
+LOCAL_INIT_RC := android.hardware.light@2.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.light@2.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/light/2.0/default/Light.cpp b/light/2.0/default/Light.cpp
new file mode 100644
index 0000000..cde1536
--- /dev/null
+++ b/light/2.0/default/Light.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "light"
+
+#include <log/log.h>
+
+#include "Light.h"
+
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+static_assert(LIGHT_FLASH_NONE == static_cast<int>(Flash::NONE),
+    "Flash::NONE must match legacy value.");
+static_assert(LIGHT_FLASH_TIMED == static_cast<int>(Flash::TIMED),
+    "Flash::TIMED must match legacy value.");
+static_assert(LIGHT_FLASH_HARDWARE == static_cast<int>(Flash::HARDWARE),
+    "Flash::HARDWARE must match legacy value.");
+
+static_assert(BRIGHTNESS_MODE_USER == static_cast<int>(Brightness::USER),
+    "Brightness::USER must match legacy value.");
+static_assert(BRIGHTNESS_MODE_SENSOR == static_cast<int>(Brightness::SENSOR),
+    "Brightness::SENSOR must match legacy value.");
+static_assert(BRIGHTNESS_MODE_LOW_PERSISTENCE ==
+    static_cast<int>(Brightness::LOW_PERSISTENCE),
+    "Brightness::LOW_PERSISTENCE must match legacy value.");
+
+Light::Light(std::map<Type, light_device_t*> &&lights)
+  : mLights(std::move(lights)) {}
+
+// Methods from ::android::hardware::light::V2_0::ILight follow.
+Return<Status> Light::setLight(Type type, const LightState& state)  {
+    auto it = mLights.find(type);
+
+    if (it == mLights.end()) {
+        return Status::LIGHT_NOT_SUPPORTED;
+    }
+
+    light_device_t* hwLight = it->second;
+
+    light_state_t legacyState {
+        .color = state.color,
+        .flashMode = static_cast<int>(state.flashMode),
+        .flashOnMS = state.flashOnMs,
+        .flashOffMS = state.flashOffMs,
+        .brightnessMode = static_cast<int>(state.brightnessMode),
+    };
+
+    int ret = hwLight->set_light(hwLight, &legacyState);
+
+    switch (ret) {
+        case -ENOSYS:
+            return Status::BRIGHTNESS_NOT_SUPPORTED;
+        case 0:
+            return Status::SUCCESS;
+        default:
+            return Status::UNKNOWN;
+    }
+}
+
+Return<void> Light::getSupportedTypes(getSupportedTypes_cb _hidl_cb)  {
+    Type *types = new Type[mLights.size()];
+
+    int idx = 0;
+    for(auto const &pair : mLights) {
+        Type type = pair.first;
+
+        types[idx++] = type;
+    }
+
+    {
+        hidl_vec<Type> hidl_types{};
+        hidl_types.setToExternal(types, mLights.size());
+
+        _hidl_cb(hidl_types);
+    }
+
+    delete[] types;
+
+    return Void();
+}
+
+const static std::map<Type, const char*> kLogicalLights = {
+    {Type::BACKLIGHT,     LIGHT_ID_BACKLIGHT},
+    {Type::KEYBOARD,      LIGHT_ID_KEYBOARD},
+    {Type::BUTTONS,       LIGHT_ID_BUTTONS},
+    {Type::BATTERY,       LIGHT_ID_BATTERY},
+    {Type::NOTIFICATIONS, LIGHT_ID_NOTIFICATIONS},
+    {Type::ATTENTION,     LIGHT_ID_ATTENTION},
+    {Type::BLUETOOTH,     LIGHT_ID_BLUETOOTH},
+    {Type::WIFI,          LIGHT_ID_WIFI}
+};
+
+light_device_t* getLightDevice(const char* name) {
+    light_device_t* lightDevice;
+    const hw_module_t* hwModule = NULL;
+
+    int ret = hw_get_module (LIGHTS_HARDWARE_MODULE_ID, &hwModule);
+    if (ret == 0) {
+        ret = hwModule->methods->open(hwModule, name,
+            reinterpret_cast<hw_device_t**>(&lightDevice));
+        if (ret != 0) {
+            ALOGE("light_open %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
+        }
+    } else {
+        ALOGE("hw_get_module %s %s failed: %d", LIGHTS_HARDWARE_MODULE_ID, name, ret);
+    }
+
+    if (ret == 0) {
+        return lightDevice;
+    } else {
+        ALOGE("Light passthrough failed to load legacy HAL.");
+        return nullptr;
+    }
+}
+
+ILight* HIDL_FETCH_ILight(const char* /* name */) {
+    std::map<Type, light_device_t*> lights;
+
+    for(auto const &pair : kLogicalLights) {
+        Type type = pair.first;
+        const char* name = pair.second;
+
+        light_device_t* light = getLightDevice(name);
+
+        if (light != nullptr) {
+            lights[type] = light;
+        }
+    }
+
+    if (lights.size() == 0) {
+        // Log information, but still return new Light.
+        // Some devices may not have any lights.
+        ALOGI("Could not open any lights.");
+    }
+
+    return new Light(std::move(lights));
+}
+
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
diff --git a/light/2.0/default/Light.h b/light/2.0/default/Light.h
new file mode 100644
index 0000000..8987036
--- /dev/null
+++ b/light/2.0/default/Light.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
+#define ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
+
+#include <android/hardware/light/2.0/ILight.h>
+#include <hardware/hardware.h>
+#include <hardware/lights.h>
+#include <hidl/Status.h>
+#include <hidl/MQDescriptor.h>
+#include <map>
+
+namespace android {
+namespace hardware {
+namespace light {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::light::V2_0::ILight;
+using ::android::hardware::light::V2_0::LightState;
+using ::android::hardware::light::V2_0::Status;
+using ::android::hardware::light::V2_0::Type;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Light : public ILight {
+    Light(std::map<Type, light_device_t*> &&lights);
+
+    // Methods from ::android::hardware::light::V2_0::ILight follow.
+    Return<Status> setLight(Type type, const LightState& state)  override;
+    Return<void> getSupportedTypes(getSupportedTypes_cb _hidl_cb)  override;
+
+private:
+    std::map<Type, light_device_t*> mLights;
+};
+
+extern "C" ILight* HIDL_FETCH_ILight(const char* name);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_LIGHT_V2_0_LIGHT_H
diff --git a/light/2.0/default/android.hardware.light@2.0-service.rc b/light/2.0/default/android.hardware.light@2.0-service.rc
new file mode 100644
index 0000000..3ba97d8
--- /dev/null
+++ b/light/2.0/default/android.hardware.light@2.0-service.rc
@@ -0,0 +1,4 @@
+service light-hal-2-0 /system/bin/hw/android.hardware.light@2.0-service
+    class hal
+    user system
+    group system
\ No newline at end of file
diff --git a/light/2.0/default/service.cpp b/light/2.0/default/service.cpp
new file mode 100644
index 0000000..70ae565
--- /dev/null
+++ b/light/2.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 "android.hardware.light@2.0-service"
+
+#include <android/hardware/light/2.0/ILight.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::light::V2_0::ILight;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<ILight>();
+}
diff --git a/light/2.0/types.hal b/light/2.0/types.hal
new file mode 100644
index 0000000..cc2ec32
--- /dev/null
+++ b/light/2.0/types.hal
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+package android.hardware.light@2.0;
+
+enum Status : int32_t {
+    SUCCESS,
+    LIGHT_NOT_SUPPORTED,
+    BRIGHTNESS_NOT_SUPPORTED,
+    UNKNOWN,
+};
+
+enum Flash : int32_t {
+    /*
+     * Keep the light steady on or off.
+     */
+    NONE,
+
+    /*
+     * Flash the light at specified rate.
+     */
+    TIMED,
+
+    /*
+     * Flash the light using hardware assist.
+     */
+    HARDWARE,
+};
+
+enum Brightness : int32_t {
+    /**
+     * Light brightness is managed by a user setting.
+     */
+    USER,
+
+    /**
+     * Light brightness is managed by a light sensor.
+     */
+    SENSOR,
+
+    /**
+     * Use a low-persistence mode for display backlights.
+     *
+     * When set, the device driver must switch to a mode optimized for low display
+     * persistence that is intended to be used when the device is being treated as a
+     * head mounted display (HMD). The actual display brightness in this mode is
+     * implementation dependent, and any value set for color in LightState may be
+     * overridden by the HAL implementation.
+     *
+     * For an optimal HMD viewing experience, the display must meet the following
+     * criteria in this mode:
+     * - Gray-to-Gray, White-to-Black, and Black-to-White switching time must be ≤ 3 ms.
+     * - The display must support low-persistence with ≤ 3.5 ms persistence.
+     *   Persistence is defined as the amount of time for which a pixel is
+     *   emitting light for a single frame.
+     * - Any "smart panel" or other frame buffering options that increase display
+     *   latency are disabled.
+     * - Display brightness is set so that the display is still visible to the user
+     *   under normal indoor lighting.
+     * - The display must update at 60 Hz at least, but higher refresh rates are
+     *   recommended for low latency.
+     *
+     */
+    LOW_PERSISTENCE,
+};
+
+/*
+ * These light IDs correspond to logical lights, not physical.
+ * So for example, if your INDICATOR light is in line with your
+ * BUTTONS, it might make sense to also light the INDICATOR
+ * light to a reasonable color when the BUTTONS are lit.
+ */
+enum Type : int32_t {
+    BACKLIGHT,
+    KEYBOARD,
+    BUTTONS,
+    BATTERY,
+    NOTIFICATIONS,
+    ATTENTION,
+    BLUETOOTH,
+    WIFI,
+
+    COUNT,
+};
+
+/**
+ * The parameters that can be set for a given light.
+ *
+ * Not all lights must support all parameters. If you
+ * can do something backward-compatible, do it.
+ */
+struct LightState {
+    /**
+     * The color of the LED in ARGB.
+     *
+     * Do your best here.
+     *   - If your light can only do red or green, if they ask for blue,
+     *     you should do green.
+     *   - If you can only do a brightness ramp, then use this formula:
+     *      unsigned char brightness = ((77*((color>>16)&0x00ff))
+     *              + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+     *   - If you can only do on or off, 0 is off, anything else is on.
+     *
+     * The high byte should be ignored. Callers will set it to 0xff (which
+     * would correspond to 255 alpha).
+     */
+    uint32_t color;
+
+    /**
+     * To flash the light at a given rate, set flashMode to LIGHT_FLASH_TIMED,
+     * and then flashOnMS should be set to the number of milliseconds to turn
+     * the light on, followed by the number of milliseconds to turn the light
+     * off.
+     */
+    Flash flashMode;
+
+    int32_t flashOnMs;
+    int32_t flashOffMs;
+
+    Brightness brightnessMode;
+};
diff --git a/light/2.0/vts/Android.mk b/light/2.0/vts/Android.mk
new file mode 100644
index 0000000..089503b
--- /dev/null
+++ b/light/2.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/light/2.0/vts/Light.vts b/light/2.0/vts/Light.vts
new file mode 100644
index 0000000..5d49822
--- /dev/null
+++ b/light/2.0/vts/Light.vts
@@ -0,0 +1,37 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "ILight"
+
+package: "android.hardware.light"
+
+import: "android.hardware.light@2.0::types"
+
+interface: {
+    api: {
+        name: "setLight"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::light::V2_0::Status"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::light::V2_0::Type"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::light::V2_0::LightState"
+        }
+    }
+
+    api: {
+        name: "getSupportedTypes"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_ENUM
+                predefined_type: "::android::hardware::light::V2_0::Type"
+            }
+        }
+    }
+
+}
diff --git a/light/2.0/vts/functional/Android.bp b/light/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..889457f
--- /dev/null
+++ b/light/2.0/vts/functional/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_test {
+    name: "light_hidl_hal_test",
+    gtest: true,
+    srcs: ["light_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+        "android.hardware.light@2.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
+
diff --git a/light/2.0/vts/functional/Android.mk b/light/2.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/light_hidl_hal_test.cpp b/light/2.0/vts/functional/light_hidl_hal_test.cpp
new file mode 100644
index 0000000..71a8b4e
--- /dev/null
+++ b/light/2.0/vts/functional/light_hidl_hal_test.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "light_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/light/2.0/ILight.h>
+#include <android/hardware/light/2.0/types.h>
+#include <gtest/gtest.h>
+#include <set>
+#include <unistd.h>
+
+using ::android::hardware::light::V2_0::Brightness;
+using ::android::hardware::light::V2_0::Flash;
+using ::android::hardware::light::V2_0::ILight;
+using ::android::hardware::light::V2_0::LightState;
+using ::android::hardware::light::V2_0::Status;
+using ::android::hardware::light::V2_0::Type;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+class LightHidlTest : public ::testing::Test {
+public:
+    virtual void SetUp() override {
+        light = ILight::getService();
+
+        ASSERT_NE(light, nullptr);
+        LOG(INFO) << "Test is remote " << light->isRemote();
+
+        ASSERT_OK(light->getSupportedTypes([this](const hidl_vec<Type> &types) {
+            supportedTypes = types;
+        }));
+    }
+
+    virtual void TearDown() override {}
+
+    sp<ILight> light;
+    std::vector<Type> supportedTypes;
+};
+
+class LightHidlEnvironment : public ::testing::Environment {
+public:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+};
+
+const static LightState kWhite = {
+    .color = 0xFFFFFFFF,
+    .flashMode = Flash::TIMED,
+    .flashOnMs = 100,
+    .flashOffMs = 50,
+    .brightnessMode = Brightness::USER,
+};
+
+const static LightState kLowPersistance = {
+    .color = 0xFF123456,
+    .flashMode = Flash::TIMED,
+    .flashOnMs = 100,
+    .flashOffMs = 50,
+    .brightnessMode = Brightness::LOW_PERSISTENCE,
+};
+
+const static LightState kOff = {
+    .color = 0x00000000,
+    .flashMode = Flash::NONE,
+    .flashOnMs = 0,
+    .flashOffMs = 0,
+    .brightnessMode = Brightness::USER,
+};
+
+const static std::set<Type> kAllTypes = {
+    Type::BACKLIGHT,
+    Type::KEYBOARD,
+    Type::BUTTONS,
+    Type::BATTERY,
+    Type::NOTIFICATIONS,
+    Type::ATTENTION,
+    Type::BLUETOOTH,
+    Type::WIFI
+};
+
+/**
+ * Ensure all lights which are reported as supported work.
+ */
+TEST_F(LightHidlTest, TestSupported) {
+    for (const Type& type: supportedTypes) {
+        Return<Status> ret = light->setLight(type, kWhite);
+        EXPECT_OK(ret);
+        EXPECT_EQ(Status::SUCCESS, static_cast<Status>(ret));
+    }
+
+    for (const Type& type: supportedTypes) {
+        Return<Status> ret = light->setLight(type, kOff);
+        EXPECT_OK(ret);
+        EXPECT_EQ(Status::SUCCESS, static_cast<Status>(ret));
+    }
+}
+
+/**
+ * Ensure BRIGHTNESS_NOT_SUPPORTED is returned if LOW_PERSISTANCE is not supported.
+ */
+TEST_F(LightHidlTest, TestLowPersistance) {
+    for (const Type& type: supportedTypes) {
+        Return<Status> ret = light->setLight(type, kLowPersistance);
+        EXPECT_OK(ret);
+
+        Status status = ret;
+        EXPECT_TRUE(Status::SUCCESS == status ||
+                    Status::BRIGHTNESS_NOT_SUPPORTED == status);
+    }
+
+    for (const Type& type: supportedTypes) {
+        Return<Status> ret = light->setLight(type, kOff);
+        EXPECT_OK(ret);
+        EXPECT_EQ(Status::SUCCESS, static_cast<Status>(ret));
+    }
+}
+
+/**
+ * Ensure lights which are not supported return LIGHT_NOT_SUPPORTED
+ */
+TEST_F(LightHidlTest, TestUnsupported) {
+    std::set<Type> unsupportedTypes = kAllTypes;
+    for (const Type& type: supportedTypes) {
+        unsupportedTypes.erase(type);
+    }
+
+    for (const Type& type: unsupportedTypes) {
+        Return<Status> ret = light->setLight(type, kWhite);
+        EXPECT_OK(ret);
+        EXPECT_EQ(Status::LIGHT_NOT_SUPPORTED, static_cast<Status>(ret));
+    }
+}
+
+int main(int argc, char **argv) {
+    ::testing::AddGlobalTestEnvironment(new LightHidlEnvironment);
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/light/2.0/vts/functional/vts/Android.mk b/light/2.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/vts/testcases/Android.mk b/light/2.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/vts/testcases/hal/Android.mk b/light/2.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/Android.mk b/light/2.0/vts/functional/vts/testcases/hal/light/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/hidl/Android.mk b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/Android.mk b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/Android.mk
new file mode 100644
index 0000000..4761a3e
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := LightHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/light/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/AndroidTest.xml b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..240f1f0
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Light HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="LightHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/light_hidl_hal_test/light_hidl_hal_test,
+            _64bit::DATA/nativetest64/light_hidl_hal_test/light_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
+
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/Android.mk b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..939929d
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := LightHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/light/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/AndroidTest.xml b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..455802d
--- /dev/null
+++ b/light/2.0/vts/functional/vts/testcases/hal/light/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Light HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="LightHidlTargetProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/light_hidl_hal_test/light_hidl_hal_test,
+            _64bit::DATA/nativetest64/light_hidl_hal_test/light_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
+
diff --git a/light/2.0/vts/types.vts b/light/2.0/vts/types.vts
new file mode 100644
index 0000000..a9c8cab
--- /dev/null
+++ b/light/2.0/vts/types.vts
@@ -0,0 +1,149 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "types"
+
+package: "android.hardware.light"
+
+
+attribute: {
+    name: "::android::hardware::light::V2_0::Status"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "LIGHT_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "BRIGHTNESS_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::light::V2_0::Flash"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TIMED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "HARDWARE"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::light::V2_0::Brightness"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "USER"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SENSOR"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "LOW_PERSISTENCE"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::light::V2_0::Type"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "BACKLIGHT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "KEYBOARD"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "BUTTONS"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "BATTERY"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "NOTIFICATIONS"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ATTENTION"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "BLUETOOTH"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "WIFI"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "COUNT"
+        scalar_value: {
+            int32_t: 8
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::light::V2_0::LightState"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "color"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "flashMode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::light::V2_0::Flash"
+    }
+    struct_value: {
+        name: "flashOnMs"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "flashOffMs"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "brightnessMode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::light::V2_0::Brightness"
+    }
+}
+
diff --git a/light/Android.bp b/light/Android.bp
new file mode 100644
index 0000000..8d2c986
--- /dev/null
+++ b/light/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "2.0",
+    "2.0/vts/functional",
+]
diff --git a/media/1.0/Android.bp b/media/1.0/Android.bp
new file mode 100644
index 0000000..d533e5a
--- /dev/null
+++ b/media/1.0/Android.bp
@@ -0,0 +1,48 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.media@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.media@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/media/1.0/types.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.media@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.media@1.0",
+    srcs: [
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/media/1.0/types.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.media@1.0",
+    generated_sources: ["android.hardware.media@1.0_genc++"],
+    generated_headers: ["android.hardware.media@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.media@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.graphics.common@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.common@1.0",
+    ],
+}
diff --git a/media/1.0/types.hal b/media/1.0/types.hal
new file mode 100644
index 0000000..89b7fa2
--- /dev/null
+++ b/media/1.0/types.hal
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media@1.0;
+
+import android.hardware.graphics.common@1.0::PixelFormat;
+
+/**
+ * Aliases
+ */
+typedef handle FileDescriptor; // This must have no more than one fd.
+typedef FileDescriptor Fence;
+typedef vec<uint8_t> Bytes;
+
+/**
+ * Ref: frameworks/native/include/ui/GraphicBuffer.h
+ * Ref: system/core/include/system/window.h: ANativeWindowBuffer
+ */
+
+/**
+ * This struct contains attributes for a gralloc buffer that can be put into a
+ * union.
+ */
+struct AnwBufferAttributes {
+    uint32_t width;
+    uint32_t height;
+    uint32_t stride;
+    PixelFormat format;
+    uint32_t usage; // TODO: convert to an enum
+    uint64_t layerCount;
+};
+
+/**
+ * An AnwBuffer is simply AnwBufferAttributes plus a native handle.
+ */
+struct AnwBuffer {
+    handle nativeHandle;
+    AnwBufferAttributes attr;
+};
+
+/**
+ * Ref: frameworks/native/include/binder/IMemory.h
+ * Ref: frameworks/native/libs/binder/IMemory.cpp
+ */
+
+/**
+ * This struct contains attributes for a shared memory buffer that can be put
+ * into a union.
+ */
+struct SharedMemoryAttributes {
+    uint32_t size;
+    uint32_t flags; // TODO: convert to an enum
+    uint32_t offset;
+};
+
+/**
+ * A SharedMemory is simply SharedMemoryAttributes plus a native handle.
+ */
+struct SharedMemory {
+    handle nativeHandle;
+    SharedMemoryAttributes attr;
+};
+
diff --git a/media/Android.bp b/media/Android.bp
new file mode 100644
index 0000000..f2abc67
--- /dev/null
+++ b/media/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "omx/1.0",
+]
diff --git a/media/omx/1.0/Android.bp b/media/omx/1.0/Android.bp
new file mode 100644
index 0000000..657c23b
--- /dev/null
+++ b/media/omx/1.0/Android.bp
@@ -0,0 +1,92 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.media.omx@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.media.omx@1.0",
+    srcs: [
+        "types.hal",
+        "IGraphicBufferSource.hal",
+        "IOmx.hal",
+        "IOmxBufferSource.hal",
+        "IOmxNode.hal",
+        "IOmxObserver.hal",
+    ],
+    out: [
+        "android/hardware/media/omx/1.0/types.cpp",
+        "android/hardware/media/omx/1.0/GraphicBufferSourceAll.cpp",
+        "android/hardware/media/omx/1.0/OmxAll.cpp",
+        "android/hardware/media/omx/1.0/OmxBufferSourceAll.cpp",
+        "android/hardware/media/omx/1.0/OmxNodeAll.cpp",
+        "android/hardware/media/omx/1.0/OmxObserverAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.media.omx@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.media.omx@1.0",
+    srcs: [
+        "types.hal",
+        "IGraphicBufferSource.hal",
+        "IOmx.hal",
+        "IOmxBufferSource.hal",
+        "IOmxNode.hal",
+        "IOmxObserver.hal",
+    ],
+    out: [
+        "android/hardware/media/omx/1.0/types.h",
+        "android/hardware/media/omx/1.0/IGraphicBufferSource.h",
+        "android/hardware/media/omx/1.0/IHwGraphicBufferSource.h",
+        "android/hardware/media/omx/1.0/BnHwGraphicBufferSource.h",
+        "android/hardware/media/omx/1.0/BpHwGraphicBufferSource.h",
+        "android/hardware/media/omx/1.0/BsGraphicBufferSource.h",
+        "android/hardware/media/omx/1.0/IOmx.h",
+        "android/hardware/media/omx/1.0/IHwOmx.h",
+        "android/hardware/media/omx/1.0/BnHwOmx.h",
+        "android/hardware/media/omx/1.0/BpHwOmx.h",
+        "android/hardware/media/omx/1.0/BsOmx.h",
+        "android/hardware/media/omx/1.0/IOmxBufferSource.h",
+        "android/hardware/media/omx/1.0/IHwOmxBufferSource.h",
+        "android/hardware/media/omx/1.0/BnHwOmxBufferSource.h",
+        "android/hardware/media/omx/1.0/BpHwOmxBufferSource.h",
+        "android/hardware/media/omx/1.0/BsOmxBufferSource.h",
+        "android/hardware/media/omx/1.0/IOmxNode.h",
+        "android/hardware/media/omx/1.0/IHwOmxNode.h",
+        "android/hardware/media/omx/1.0/BnHwOmxNode.h",
+        "android/hardware/media/omx/1.0/BpHwOmxNode.h",
+        "android/hardware/media/omx/1.0/BsOmxNode.h",
+        "android/hardware/media/omx/1.0/IOmxObserver.h",
+        "android/hardware/media/omx/1.0/IHwOmxObserver.h",
+        "android/hardware/media/omx/1.0/BnHwOmxObserver.h",
+        "android/hardware/media/omx/1.0/BpHwOmxObserver.h",
+        "android/hardware/media/omx/1.0/BsOmxObserver.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.media.omx@1.0",
+    generated_sources: ["android.hardware.media.omx@1.0_genc++"],
+    generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/media/omx/1.0/IGraphicBufferSource.hal b/media/omx/1.0/IGraphicBufferSource.hal
new file mode 100644
index 0000000..9b3ab0c
--- /dev/null
+++ b/media/omx/1.0/IGraphicBufferSource.hal
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+import android.hardware.graphics.common@1.0::Dataspace;
+
+import android.hardware.media@1.0::types;
+
+import IOmxNode;
+
+/**
+ * Ref: frameworks/av/media/libmedia/aidl/android/IGraphicBufferSource.aidl
+ *
+ * TODO: Add documentations.
+ */
+interface IGraphicBufferSource {
+
+    configure(IOmxNode omxNode, Dataspace dataspace);
+
+    setSuspend(bool suspend);
+
+    setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs);
+
+    setMaxFps(float maxFps);
+
+    setTimeLapseConfig(int64_t timePerFrameUs, int64_t timePerCaptureUs);
+
+    setStartTimeUs(int64_t startTimeUs);
+
+    setColorAspects(ColorAspects aspects);
+
+    setTimeOffsetUs(int64_t timeOffsetUs);
+
+    signalEndOfInputStream();
+
+};
+
diff --git a/media/omx/1.0/IOmx.hal b/media/omx/1.0/IOmx.hal
new file mode 100644
index 0000000..e9f0b76
--- /dev/null
+++ b/media/omx/1.0/IOmx.hal
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+import android.hardware.media@1.0::types;
+
+import IOmxNode;
+import IOmxObserver;
+
+/**
+ * Ref: frameworks/av/include/media/IOMX.h: IOMX
+ *
+ * IOmx is the main entry point for communicating with OMX components.
+ */
+interface IOmx {
+
+    /**
+     * Information for an IOmxNode component.
+     */
+    struct ComponentInfo {
+        string mName;       //< Name of the component.
+        vec<string> mRoles; //< Roles of the component.
+    };
+
+    /**
+     * List available components.
+     *
+     * @param[out] status will be the status of the call.
+     * @param[out] nodeList will be a list of ComponentInfo.
+     */
+    listNodes(
+        ) generates (
+            Status status,
+            vec<ComponentInfo> nodeList
+        );
+
+    /**
+     * Allocate an IOmxNode instance with the specified component name.
+     *
+     * @param[in] name is the name of the component to create.
+     * @param[in] observer is an observer object that will receive messages from
+     * the created instance.
+     * @param[out] status will be the status of the call.
+     * @param[out] omxNode will be the allocated instance of IOmxNode.
+     */
+    allocateNode(
+            string name,
+            IOmxObserver observer
+        ) generates (
+            Status status,
+            IOmxNode omxNode
+        );
+
+};
+
diff --git a/media/omx/1.0/IOmxBufferSource.hal b/media/omx/1.0/IOmxBufferSource.hal
new file mode 100644
index 0000000..94c43fc
--- /dev/null
+++ b/media/omx/1.0/IOmxBufferSource.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+import android.hardware.media@1.0::types;
+
+/**
+ * Ref: frameworks/av/media/libmedia/aidl/android/IOMXBufferSource.aidl
+ *
+ * IOmxBufferSource is an interface for a listener for certain events from an
+ * IOmxNode instance. Use IOmxNode::setInputSurface() to attach an
+ * IOmxBufferSource instance to an IOmxNode instance.
+ *
+ * @see OMX_STATETYPE in the OpenMax IL standard.
+ */
+interface IOmxBufferSource {
+
+    /**
+     * onOmxExecuting() is invoked when the node state changes to
+     * OMX_StateExecuting state.
+     */
+    oneway onOmxExecuting();
+
+    /**
+     * onOmxIdle() is invoked when the node transitions from OMX_StateExecuting
+     * to OMX_StateIdle.
+     */
+    oneway onOmxIdle();
+
+    /**
+     * onOmxLoaded() is invoked when the node transitions from OMX_StateIdle or
+     * OMX_StateExecuting to OMX_StateLoaded.
+     */
+    oneway onOmxLoaded();
+
+    /**
+     * onInputBufferAdded() is invoked after a new input buffer is added to the
+     * node. This may happen within IOmxNode::allocateSecureBuffer() or
+     * IOmxNode::useBuffer().
+     *
+     * @param[in] buffer is the id of the added buffer.
+     */
+    oneway onInputBufferAdded(BufferId buffer);
+
+    /**
+     * onInputBufferEmptied() is invoked after an input buffer is emptied. This
+     * may happen within IOmxNode::emptyBuffer().
+     *
+     * @param[in] buffer is the id of the emptied buffer.
+     * @param[in] fence is the fence associated with the buffer.
+     */
+    oneway onInputBufferEmptied(BufferId buffer, Fence fence);
+};
+
diff --git a/media/omx/1.0/IOmxNode.hal b/media/omx/1.0/IOmxNode.hal
new file mode 100644
index 0000000..5945b44
--- /dev/null
+++ b/media/omx/1.0/IOmxNode.hal
@@ -0,0 +1,358 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+import IOmxBufferSource;
+
+import android.hardware.media@1.0::types;
+
+/**
+ * Ref: frameworks/av/include/media/IOMX.h: IOMXNode
+ * Ref: https://www.khronos.org/registry/omxil/specs/OpenMAX_IL_1_1_2_Specification.pdf
+ */
+
+/**
+ * IOmxNode is an interface for communicating with an OMX component (called
+ * "node" here) that has been previously obtained by calling
+ * IOmx::allocateNode().
+ */
+interface IOmxNode {
+
+    /**
+     * Free the node.
+     *
+     * @param[out] status will be the status of the call.
+     */
+    freeNode(
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Invoke a command on the node.
+     *
+     * @param[in] cmd indicates the type of the command.
+     * @param[in] param is a parameter for the command.
+     * @param[out] status will be the status of the call.
+     *
+     * @see OMX_SendCommand() in the OpenMax IL standard.
+     */
+    sendCommand(
+            uint32_t cmd,
+            int32_t param
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Retrieve a parameter setting from the node.
+     *
+     * @param[in] index indicates the type of the parameter to retrieve.
+     * @param[in] inParams holds some information about the retrieval.
+     * @param[out] status will be the status of the call.
+     * @param[out] outParams will be the current parameter setting.
+     *
+     * @see OMX_GetParameter() in the OpenMax IL standard.
+     */
+    getParameter(
+            uint32_t index,
+            Bytes inParams // TODO: describe structure better or point at standard
+        ) generates (
+            Status status,
+            Bytes outParams // TODO: describe structure better or point at standard
+        );
+
+    /**
+     * Change a parameter setting of the node.
+     *
+     * @param[in] index indicates the type of the parameter to change.
+     * @param[in] params holds the new parameter setting.
+     * @param[out] status will be the status of the call.
+     *
+     * @see OMX_SetParameter() in the OpenMax IL standard.
+     */
+    setParameter(
+            uint32_t index,
+            Bytes params // TODO: describe structure better or point at standard
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Retrieve a configuration from the node.
+     *
+     * @param[in] index indicates the type of the configuration to retrieve.
+     * @param[in] inConfig holds some information about the retrieval.
+     * @param[out] status will be the status of the call.
+     * @param[out] outConfig will be the current configuration.
+     *
+     * @see OMX_GetConfig() in the OpenMax IL standard.
+     */
+    getConfig(
+            uint32_t index,
+            Bytes inConfig // TODO: describe structure better or point at standard
+        ) generates (
+            Status status,
+            Bytes outConfig // TODO: describe structure better or point at standard
+        );
+
+    /**
+     * Change a configuration of the node.
+     *
+     * @param[in] index indicates the type of the configuration to change.
+     * @param[in] config holds the new configuration.
+     * @param[out] status will be the status of the call.
+     *
+     * @see OMX_SetConfig() in the OpenMax IL standard.
+     */
+    setConfig(
+            uint32_t index,
+            Bytes config // TODO: describe structure better or point at standard
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Set the mode of a port on the node.
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] mode is the target mode on the specified port.
+     */
+    setPortMode(
+            uint32_t portIndex,
+            PortMode mode
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Prepare a port for adaptive playback. This is based on the extension
+     * "OMX.google.android.index.prepareForAdaptivePlayback".
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] enable indicates whether adaptive playback is enabled or not.
+     * @param[in] maxFrameWidth specifies the maximum frame width.
+     * @param[in] maxFrameHeight specifies the maximum frame height.
+     * @param[out] status status will be the status of the call.
+     */
+    prepareForAdaptivePlayback(
+            uint32_t portIndex,
+            bool enable,
+            uint32_t maxFrameWidth,
+            uint32_t maxFrameHeight
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Configure a port for a tunneled playback mode. This is based on the
+     * extension "OMX.google.android.index.configureVideoTunnelMode".
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] tunneled indicates whether the tunneled mode is used or not.
+     * @param[in] audioHwSync is the HW SYNC ID of the audio HAL output stream
+     * to sync the video with.
+     * @param[out] status will be the status of the call.
+     * @param[out] sidebandHandle will contain the codec-allocated sideband
+     * window handle.
+     */
+    configureVideoTunnelMode(
+            uint32_t portIndex,
+            bool tunneled,
+            uint32_t audioHwSync
+        ) generates (
+            Status status,
+            handle sidebandHandle
+        );
+
+    /**
+     * Retrieve the buffer usage on a port. This is based on the extension
+     * "OMX.google.android.index.getAndroidNativeBufferUsage".
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[out] status will be the status of the call.
+     * @param[out] usage will be the usage.
+     */
+    getGraphicBufferUsage(
+            uint32_t portIndex
+        ) generates (
+            Status status,
+            uint32_t usage // TODO: Ask graphics team to define an enum.
+        );
+
+    /**
+     * Set up a listener to events related to the input surface.
+     *
+     * @param[in] bufferSource is the listener object that implements
+     * IOmxBufferSource.
+     * @param[out] status will be the status of the call.
+     *
+     * @see IOmxBufferSource.
+     */
+    setInputSurface(
+            IOmxBufferSource bufferSource
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Allocate an opaque buffer on a port as a native handle.
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] size is the desired size of the buffer.
+     * @param[out] status will be the status of the call.
+     * @param[out] buffer will be the id of the allocated buffer, which will be
+     * needed in some other buffer-related function calls.
+     * @param[out] nativeHandle will be the native handle of the allocated
+     * buffer.
+     *
+     * @see OMX_AllocateBuffer() in the OpenMax IL standard.
+     */
+    allocateSecureBuffer(
+            uint32_t portIndex,
+            uint64_t size
+        ) generates (
+            Status status,
+            BufferId buffer,
+            handle nativeHandle
+        );
+
+    /**
+     * Assign a buffer to a port.
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] omxBuffer is the buffer to be assigned to the port.
+     * @param[out] status will be the status of the call.
+     * @param[out] buffer will be the id of the assigned buffer, which will be
+     * needed in some other buffer-related function calls.
+     *
+     * @see OMX_UseBuffer() in the OpenMax IL standard.
+     */
+    useBuffer(
+            uint32_t portIndex,
+            CodecBuffer omxBuffer
+        ) generates (
+            Status status,
+            BufferId buffer
+        );
+
+    /**
+     * Free a buffer previously assigned to a port by allocateSecureBuffer() or
+     * useBuffer().
+     *
+     * @param[in] portIndex is the index of the port.
+     * @param[in] buffer is the id of the buffer to be freed.
+     * @param[out] status will be the status of the call.
+     *
+     * @see OMX_FreeBuffer() in the OpenMax IL standard.
+     */
+    freeBuffer(
+            uint32_t portIndex,
+            BufferId buffer
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Pass \p fence to the node if it supports fences. Otherwise, it waits on
+     * \p fence before calling OMX_FillThisBuffer(). The node will take
+     * ownership of the fence even if this call fails.
+     *
+     * If the port is in metadata mode, the buffer will be updated to point to
+     * the new buffer passed in via \p omxBuffer before OMX_FillThisBuffer() is
+     * called. Otherwise, \p omxBuffer is not used.
+     *
+     * @param[in] buffer is the id of the buffer to fill.
+     * @param[in] omxBuffer points to the new buffer in metadata mode.
+     * @param[in] fence is the fence to wait for (if not null).
+     * @param[out] status is the status of the call.
+     *
+     * @see OMX_FillThisBuffer() in the OpenMax IL standard.
+     */
+    fillBuffer(
+            BufferId buffer,
+            CodecBuffer omxBuffer,
+            Fence fence
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Pass \p fence to the node if it supports fences. Otherwise, wait on
+     * \p fence before calling OMX_EmptyThisBuffer(). The node will take
+     * ownership of the fence even if this call fails.
+     *
+     * If the port is in metadata mode, the buffer will be updated to point to
+     * the new buffer passed in via \p omxBuffer before OMX_EmptyThisBuffer() is
+     * called. Otherwise, \p omxBuffer is not used.
+     *
+     * @param[in] buffer is the id of the buffer to fill.
+     * @param[in] omxBuffer points to the new buffer in metadata mode.
+     * @param[in] flags is put into the header information that is passed to
+     * OMX_EmptyBuffer().
+     * @param[in] timestampUs is put into the header information that is passed
+     * to OMX_EmptyBuffer().
+     * @param[in] fence is the fence to wait for (if not null).
+     * @param[out] status is the status of the call.
+     *
+     * @see OMX_EmptyThisBuffer() in the OpenMax IL standard.
+     */
+    emptyBuffer(
+            BufferId buffer,
+            CodecBuffer omxBuffer,
+            uint32_t flags, // TODO: describe structure better or point at standard
+            uint64_t timestampUs,
+            Fence fence
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Request the node to translate an extension string to an index.
+     *
+     * @param[in] parameterName is the requested extension string.
+     * @param[out] status is the status of the call.
+     * @param[out] index is the translated index.
+     *
+     * @see OMX_GetExtensionIndex() in the OpenMax IL standard.
+     */
+    getExtensionIndex(
+            string parameterName
+        ) generates (
+            Status status,
+            uint32_t index
+        );
+
+    /**
+     * Add an OMX message on the node's message queue. The instance of
+     * IOmxObserver that was obtained during the creation of the node will
+     * receive the message in batches by the callback
+     * IOmxObserver::onMessages().
+     *
+     * @param[in] msg is the message to send.
+     * @param[out] status is the status of the call.
+     *
+     * @see IOmxObserver::onMessages().
+     */
+    dispatchMessage(
+            Message msg
+        ) generates (
+            Status status
+        );
+
+};
+
diff --git a/media/omx/1.0/IOmxObserver.hal b/media/omx/1.0/IOmxObserver.hal
new file mode 100644
index 0000000..c26a937
--- /dev/null
+++ b/media/omx/1.0/IOmxObserver.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+/**
+ * Ref: frameworks/av/include/media/IOMX.h: IOMXObserver
+ */
+
+/**
+ * IOmxObserver is a listener interface for OMX messages sent from an IOmxNode
+ * stance.
+ */
+interface IOmxObserver {
+
+    /**
+     * Invoked to process messages from an IOmxNode instance. Note that messages
+     * come in batches.
+     */
+    oneway onMessages(vec<Message> messages);
+};
+
diff --git a/media/omx/1.0/types.hal b/media/omx/1.0/types.hal
new file mode 100644
index 0000000..ccb2ddf
--- /dev/null
+++ b/media/omx/1.0/types.hal
@@ -0,0 +1,264 @@
+/*
+ * 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.
+ */
+
+package android.hardware.media.omx@1.0;
+
+import android.hardware.media@1.0::types;
+
+// Aliases
+typedef uint32_t BufferId;
+
+/**
+ * Ref: system/core/include/utils/Errors.h
+ * Ref: bionic/libc/kernel/uapi/asm-generic/errno-base.h
+ * Ref: bionic/libc/kernel/uapi/asm-generic/errno.h
+ * Ref: frameworks/av/include/media/stagefright/MediaError.h
+ * Ref: frameworks/av/media/libstagefright/omx/OMXUtils.cpp: StatusFromOMXError
+ */
+enum Status : int32_t {
+    OK                      = 0,
+    NO_ERROR                = 0,
+
+    NAME_NOT_FOUND          = -2,
+    NO_MEMORY               = -12,
+    BAD_VALUE               = -22,
+    ERROR_UNSUPPORTED       = -1010,
+    UNKNOWN_ERROR           = -2147483648,
+};
+
+/**
+ * Ref: frameworks/av/include/media/IOMX.h: omx_message
+ *
+ * Data structure for an OMX message. This is essentially a union of different
+ * message types.
+ */
+struct Message {
+
+    /**
+     * There are four main types of messages.
+     */
+    enum Type : uint32_t {
+        EVENT,
+        EMPTY_BUFFER_DONE,
+        FILL_BUFFER_DONE,
+        FRAME_RENDERED,
+    };
+
+    /**
+     * @see OMX_EVENTTYPE in the OpenMax IL standard.
+     */
+    struct EventData {
+        uint32_t event; // TODO: if there are common core events, convert to an enum or point to std
+        uint32_t data1;
+        uint32_t data2;
+        uint32_t data3;
+        uint32_t data4;
+    };
+
+    struct BufferData {
+        BufferId buffer;
+    };
+
+    struct ExtendedBufferData {
+        BufferId buffer;
+        uint32_t rangeOffset;
+        uint32_t rangeLength;
+        uint32_t flags; // TODO: if common flags exist, define an enum of point to std
+        uint64_t timestampUs;
+    };
+
+    struct RenderData {
+        uint64_t timestampUs;
+        int64_t systemTimeNs;
+    };
+
+    union Data {
+        // if type == EVENT
+        EventData eventData;
+
+        // if type == EMPTY_BUFFER_DONE
+        BufferData bufferData;
+
+        // if type == FILL_BUFFER_DONE
+        ExtendedBufferData extendedBufferData;
+
+        // if type == FRAME_RENDERED
+        RenderData renderData;
+    };
+
+    /**
+     * The type of the message.
+     */
+    Type type;
+
+    /**
+     * The fence associated with the message.
+     */
+    Fence fence;
+
+    /**
+     * The union of data, discriminated by type.
+     */
+    Data data;
+};
+
+/**
+ * Ref: frameworks/native/include/ui/GraphicBuffer.h
+ * Ref: system/core/include/system/window.h
+ * Ref: frameworks/native/include/binder/IMemory.h
+ * Ref: frameworks/native/libs/binder/IMemory.cpp
+ * Ref: frameworks/av/include/media/OMXBuffer.h
+ *
+ * Data structure for buffer information. This is essentially a union of
+ * different buffer types.
+ */
+struct CodecBuffer {
+
+    /**
+     * There are four main types of buffers.
+     */
+    enum Type : int32_t {
+        INVALID = 0,
+        PRESET,
+        SHARED_MEM,
+        ANW_BUFFER,
+        NATIVE_HANDLE
+    };
+
+    struct PresetAttributes {
+        uint32_t rangeLength;
+    };
+
+    union Attributes {
+        // if bufferType == PRESET
+        PresetAttributes preset;
+
+        // if bufferType == SHARED_MEM
+        SharedMemoryAttributes sharedMem;
+
+        // if bufferType == ANW_BUFFER
+        AnwBufferAttributes anwBuffer;
+
+        // if bufferType == NATIVE_HANDLE
+        // No additional attributes.
+    };
+
+    /**
+     * Type of the buffer.
+     */
+    Type type;
+
+    /**
+     * Attributes that can be put into a union.
+     */
+    Attributes attr;
+
+    /**
+     * \p nativeHandle is used only for types SHARED_MEM, ANW_BUFFER and
+     * NATIVE_HANDLE.
+     *
+     * (A native handle cannot be put into a union as HIDL currently does not
+     * support discriminated unions.)
+     */
+    handle nativeHandle;
+
+};
+
+/**
+ * Ref: frameworks/av/include/media/IOMX.h
+ *
+ * Enumeration of port modes.
+ */
+enum PortMode : int32_t {
+    PRESET_START = 0,
+    PRESET_BYTE_BUFFER,
+    PRESET_ANW_BUFFER,
+    PRESET_SECURE_BUFFER,
+    PRESET_END,
+    DYNAMIC_START = 100,
+    DYNAMIC_ANW_BUFFER,
+    DYNAMIC_NATIVE_HANDLE,
+    DYNAMIC_END
+};
+
+/**
+ * Ref: frameworks/native/include/media/hardware/VideoAPI.h
+ *
+ * Framework defined color aspects. These are based mainly on ISO 23001-8 spec. As this standard
+ * continues to evolve, new values may be defined in the future. Use OTHER for these future values
+ * as well as for values not listed here, as those are not supported by the framework.
+ */
+struct ColorAspects {
+    enum Range : uint32_t {
+        UNSPECIFIED,  // Unspecified
+        FULL,         // Full range
+        LIMITED,      // Limited range (if defined), or not full range
+
+        OTHER = 0xff, // Not one of the above values
+    };
+
+    // Color primaries
+    enum Primaries : uint32_t {
+        UNSPECIFIED,  // Unspecified
+        BT709_5,      // Rec.ITU-R BT.709-5 or equivalent
+        BT470_6M,     // Rec.ITU-R BT.470-6 System M or equivalent
+        BT601_6_625,  // Rec.ITU-R BT.601-6 625 or equivalent
+        BT601_6_525,  // Rec.ITU-R BT.601-6 525 or equivalent
+        GENERIC_FILM, // Generic Film
+        BT2020,       // Rec.ITU-R BT.2020 or equivalent
+
+        OTHER = 0xff, // Not one of the above values
+    };
+
+    // Transfer characteristics
+    enum Transfer : uint32_t {
+        UNSPECIFIED,  // Unspecified
+        LINEAR,       // Linear transfer characteristics
+        SRGB,         // sRGB or equivalent
+        SMPTE170M,    // SMPTE 170M or equivalent (e.g. BT.601/709/2020)
+        GAMMA22,      // Assumed display gamma 2.2
+        GAMMA28,      // Assumed display gamma 2.8
+        ST2084,       // SMPTE ST 2084 for 10/12/14/16 bit systems
+        HLG,          // ARIB STD-B67 hybrid-log-gamma
+
+        // values unlikely to be required by Android follow here
+        SMPTE240M = 0x40, // SMPTE 240M
+        XVYCC,        // IEC 61966-2-4
+        BT1361,       // Rec.ITU-R BT.1361 extended gamut
+        ST428,        // SMPTE ST 428-1
+
+        OTHER = 0xff, // Not one of the above values
+    };
+
+    // YUV <-> RGB conversion
+    enum MatrixCoeffs : uint32_t {
+        UNSPECIFIED,    // Unspecified
+        BT709_5,        // Rec.ITU-R BT.709-5 or equivalent
+        BT470_6M,       // KR=0.30, KB=0.11 or equivalent
+        BT601_6,        // Rec.ITU-R BT.601-6 625 or equivalent
+        SMPTE240M,      // SMPTE 240M or equivalent
+        BT2020,         // Rec.ITU-R BT.2020 non-constant luminance
+        BT2020CONSTANT, // Rec.ITU-R BT.2020 constant luminance
+
+        OTHER = 0xff,   // Not one of the above values
+    };
+
+    Range range;
+    Primaries primaries;
+    Transfer transfer;
+    MatrixCoeffs matrixCoeffs;
+};
+
diff --git a/memtrack/1.0/Android.bp b/memtrack/1.0/Android.bp
new file mode 100644
index 0000000..36e7594
--- /dev/null
+++ b/memtrack/1.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.memtrack@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0",
+    srcs: [
+        "types.hal",
+        "IMemtrack.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/types.cpp",
+        "android/hardware/memtrack/1.0/MemtrackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.memtrack@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0",
+    srcs: [
+        "types.hal",
+        "IMemtrack.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/types.h",
+        "android/hardware/memtrack/1.0/IMemtrack.h",
+        "android/hardware/memtrack/1.0/IHwMemtrack.h",
+        "android/hardware/memtrack/1.0/BnHwMemtrack.h",
+        "android/hardware/memtrack/1.0/BpHwMemtrack.h",
+        "android/hardware/memtrack/1.0/BsMemtrack.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.memtrack@1.0",
+    generated_sources: ["android.hardware.memtrack@1.0_genc++"],
+    generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.memtrack.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/memtrack/1.0/ $(genDir)/android/hardware/memtrack/1.0/",
+    srcs: [
+        "types.hal",
+        "IMemtrack.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/types.vts.cpp",
+        "android/hardware/memtrack/1.0/Memtrack.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.memtrack.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/memtrack/1.0/ $(genDir)/android/hardware/memtrack/1.0/",
+    srcs: [
+        "types.hal",
+        "IMemtrack.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/types.vts.h",
+        "android/hardware/memtrack/1.0/Memtrack.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.memtrack.vts.driver@1.0",
+    generated_sources: ["android.hardware.memtrack.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.memtrack.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.memtrack.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.memtrack@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.memtrack@1.0-IMemtrack-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/memtrack/1.0/ $(genDir)/android/hardware/memtrack/1.0/",
+    srcs: [
+        "IMemtrack.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/Memtrack.vts.cpp",
+        "android/hardware/memtrack/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.memtrack@1.0-IMemtrack-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.memtrack@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/memtrack/1.0/ $(genDir)/android/hardware/memtrack/1.0/",
+    srcs: [
+        "IMemtrack.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/memtrack/1.0/Memtrack.vts.h",
+        "android/hardware/memtrack/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.memtrack@1.0-IMemtrack-vts.profiler",
+    generated_sources: ["android.hardware.memtrack@1.0-IMemtrack-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.memtrack@1.0-IMemtrack-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.memtrack@1.0-IMemtrack-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.memtrack@1.0",
+    ],
+}
diff --git a/memtrack/1.0/Android.mk b/memtrack/1.0/Android.mk
new file mode 100644
index 0000000..eeb67f6
--- /dev/null
+++ b/memtrack/1.0/Android.mk
@@ -0,0 +1,232 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.memtrack@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (MemtrackFlag)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackRecord)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackRecord.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackRecord
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackStatus)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackType)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IMemtrack.hal
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/IMemtrack.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMemtrack.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::IMemtrack
+
+$(GEN): $(LOCAL_PATH)/IMemtrack.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.memtrack@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (MemtrackFlag)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackRecord)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackRecord.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackRecord
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackStatus)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MemtrackType)
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/MemtrackType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::types.MemtrackType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IMemtrack.hal
+#
+GEN := $(intermediates)/android/hardware/memtrack/V1_0/IMemtrack.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMemtrack.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.memtrack@1.0::IMemtrack
+
+$(GEN): $(LOCAL_PATH)/IMemtrack.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/memtrack/1.0/IMemtrack.hal b/memtrack/1.0/IMemtrack.hal
new file mode 100644
index 0000000..ae9d960
--- /dev/null
+++ b/memtrack/1.0/IMemtrack.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+package android.hardware.memtrack@1.0;
+
+/*
+ * The Memory Tracker HAL is designed to return information about
+ * device-specific memory usage.
+ * The primary goal is to be able to track memory that is not
+ * trackable in any other way, for example texture memory that is allocated by
+ * a process, but not mapped in to that process's address space.
+ * A secondary goal is to be able to categorize memory used by a process into
+ * GL, graphics, etc. All memory sizes must be in real memory usage,
+ * accounting for stride, bit depth, rounding up to page size, etc.
+ *
+ * Constructor for the interface should be used to perform memtrack management
+ * setup actions and is called once before any calls to getMemory().
+ */
+interface IMemtrack {
+    /*
+     * getMemory() populates MemtrackRecord vector with the sizes of memory
+     * plus associated flags for that memory.
+     *
+     * This function must be thread-safe, it may get called from multiple
+     * threads at the same time.
+     *
+     * A process collecting memory statistics will call getMemory for each
+     * combination of pid and memory type. For each memory type that it
+     * recognizes, the HAL must fill out an array of memtrack_record
+     * structures breaking down the statistics of that memory type as much as
+     * possible. For example,
+     * getMemory(<pid>, GL) might return:
+     * { { 4096,  ACCOUNTED | PRIVATE | SYSTEM },
+     *   { 40960, UNACCOUNTED | PRIVATE | SYSTEM },
+     *   { 8192,  ACCOUNTED | PRIVATE | DEDICATED },
+     *   { 8192,  UNACCOUNTED | PRIVATE | DEDICATED } }
+     * If the HAL cannot differentiate between SYSTEM and DEDICATED memory, it
+     * could return:
+     * { { 12288,  ACCOUNTED | PRIVATE },
+     *   { 49152,  UNACCOUNTED | PRIVATE } }
+     *
+     * Memory must not overlap between types. For example, a graphics buffer
+     * that has been mapped into the GPU as a surface must show up when
+     * GRAPHICS is requested and not when GL
+     * is requested.
+     *
+     * @param pid process for which memory information is requested
+     * @param type memory type that information is being requested about
+     * @return records vector of MemtrackRecord containing memory information
+     * @return retval SUCCESS on success, TYPE_NOT_FOUND if the type is not
+     * supported.
+     */
+    getMemory(int32_t pid, MemtrackType type)
+            generates (MemtrackStatus retval, vec<MemtrackRecord> records);
+};
diff --git a/memtrack/1.0/default/Android.bp b/memtrack/1.0/default/Android.bp
new file mode 100644
index 0000000..91fa1ea
--- /dev/null
+++ b/memtrack/1.0/default/Android.bp
@@ -0,0 +1,51 @@
+// 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.memtrack@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Memtrack.cpp"],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libhardware",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.memtrack@1.0",
+    ],
+
+}
+
+cc_binary {
+    relative_install_path: "hw",
+    name: "android.hardware.memtrack@1.0-service",
+    init_rc: ["android.hardware.memtrack@1.0-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libbase",
+        "libdl",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "android.hardware.memtrack@1.0",
+    ],
+
+}
diff --git a/memtrack/1.0/default/Memtrack.cpp b/memtrack/1.0/default/Memtrack.cpp
new file mode 100644
index 0000000..cc2d341
--- /dev/null
+++ b/memtrack/1.0/default/Memtrack.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.memtrack@1.0-impl"
+
+#include <log/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/memtrack.h>
+
+#include "Memtrack.h"
+
+namespace android {
+namespace hardware {
+namespace memtrack {
+namespace V1_0 {
+namespace implementation {
+
+Memtrack::Memtrack(const memtrack_module_t *module) : mModule(module) {
+    if (mModule)
+        mModule->init(mModule);
+}
+
+Memtrack::~Memtrack() {
+    delete(mModule);
+}
+
+Return<void> Memtrack::getMemory(int32_t pid, MemtrackType type,
+        getMemory_cb _hidl_cb)  {
+    hidl_vec<MemtrackRecord> records;
+    size_t temp = 0;
+    size_t *size = &temp;
+    int ret = 0;
+
+    if (mModule->getMemory == nullptr)
+    {
+        _hidl_cb(MemtrackStatus::SUCCESS, records);
+        return Void();
+    }
+    ret = mModule->getMemory(mModule, pid, static_cast<memtrack_type>(type),
+            NULL, size);
+    if (ret == 0)
+    {
+        memtrack_record *legacy_records = new memtrack_record[*size];
+        ret = mModule->getMemory(mModule, pid,
+                static_cast<memtrack_type>(type), legacy_records, size);
+        if (ret == 0)
+        {
+            records.resize(*size);
+            for(size_t i = 0; i < *size; i++)
+            {
+                records[i].sizeInBytes = legacy_records[i].size_in_bytes;
+                records[i].flags = legacy_records[i].flags;
+            }
+        }
+        delete[] legacy_records;
+    }
+    _hidl_cb(MemtrackStatus::SUCCESS, records);
+    return Void();
+}
+
+
+IMemtrack* HIDL_FETCH_IMemtrack(const char* name) {
+    const hw_module_t* hw_module = nullptr;
+    const memtrack_module_t* memtrack_module = nullptr;
+    int err = hw_get_module(name, &hw_module);
+    if (err) {
+        ALOGE ("hw_get_module %s failed: %d", name, err);
+        return nullptr;
+    }
+
+    if (!hw_module->methods || !hw_module->methods->open) {
+        memtrack_module = reinterpret_cast<const memtrack_module_t*>(hw_module);
+    } else {
+        err = hw_module->methods->open(hw_module, name,
+                reinterpret_cast<hw_device_t**>(const_cast<memtrack_module_t**>(&memtrack_module)));
+        if (err) {
+            ALOGE("Passthrough failed to load legacy HAL.");
+            return nullptr;
+        }
+    }
+    return new Memtrack(memtrack_module);
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace memtrack
+}  // namespace hardware
+}  // namespace android
diff --git a/memtrack/1.0/default/Memtrack.h b/memtrack/1.0/default/Memtrack.h
new file mode 100644
index 0000000..0adba76
--- /dev/null
+++ b/memtrack/1.0/default/Memtrack.h
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_MEMTRACK_V1_0_MEMTRACK_H
+#define ANDROID_HARDWARE_MEMTRACK_V1_0_MEMTRACK_H
+
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace memtrack {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::memtrack::V1_0::IMemtrack;
+using ::android::hardware::memtrack::V1_0::MemtrackRecord;
+using ::android::hardware::memtrack::V1_0::MemtrackStatus;
+using ::android::hardware::memtrack::V1_0::MemtrackType;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Memtrack : public IMemtrack {
+    Memtrack(const memtrack_module_t* module);
+    ~Memtrack();
+    Return<void> getMemory(int32_t pid, MemtrackType type, getMemory_cb _hidl_cb)  override;
+
+  private:
+    const memtrack_module_t* mModule;
+};
+
+extern "C" IMemtrack* HIDL_FETCH_IMemtrack(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace memtrack
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_MEMTRACK_V1_0_MEMTRACK_H
diff --git a/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
new file mode 100644
index 0000000..14e7d00
--- /dev/null
+++ b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
@@ -0,0 +1,4 @@
+service memtrack-hal-1-0 /system/bin/hw/android.hardware.memtrack@1.0-service
+    class hal
+    user system
+    group system
diff --git a/memtrack/1.0/default/service.cpp b/memtrack/1.0/default/service.cpp
new file mode 100644
index 0000000..f705b15
--- /dev/null
+++ b/memtrack/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.memtrack@1.0-service"
+
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::memtrack::V1_0::IMemtrack;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IMemtrack>("memtrack");
+}
diff --git a/memtrack/1.0/types.hal b/memtrack/1.0/types.hal
new file mode 100644
index 0000000..3d702b3
--- /dev/null
+++ b/memtrack/1.0/types.hal
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package android.hardware.memtrack@1.0;
+
+/*
+ * SMAPS_ACCOUNTED/SMAPS_UNACCOUNTED
+ * Flags to differentiate memory that can already be accounted for in
+ * /proc/<pid>/smaps,
+ * (Shared_Clean + Shared_Dirty + Private_Clean + Private_Dirty = Size).
+ * In general, memory mapped in to a userspace process is accounted unless
+ * it was mapped with remap_pfn_range.
+ * Exactly one of these must be set.
+ *
+ * SHARED/SHARED_PSS/PRIVATE
+ * Flags to differentiate memory shared across multiple processes vs. memory
+ * used by a single process.
+ * If SHARED_PSS flags is used, the memory must be divided by the number of
+ * processes holding reference to it (shared / num_processes).
+ * Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count shared + private memory.
+ *
+ * SYSTEM/DEDICATED
+ * Flags to differentiate memory taken from the kernel's allocation pool vs.
+ * memory that is dedicated to non-kernel allocations, for example a carveout
+ * or separate video memory.  Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count system + dedicated memory.
+ *
+ * NONSECURE/SECURE
+ * Flags to differentiate memory accessible by the CPU in non-secure mode vs.
+ * memory that is protected.  Only zero or one of these may be set in a record.
+ * If none are set, record is assumed to count secure + nonsecure memory.
+ */
+enum MemtrackFlag : uint32_t {
+    SMAPS_ACCOUNTED = 1 << 1,
+    SMAPS_UNACCOUNTED = 1 << 2,
+    SHARED = 1 << 3,
+    SHARED_PSS = 1 << 4,
+    PRIVATE = 1 << 5,
+    SYSTEM = 1 << 6,
+    DEDICATED = 1 << 7,
+    NONSECURE = 1 << 8,
+    SECURE = 1 << 9,
+};
+
+/* Tags which define the usage of the memory buffers. */
+enum MemtrackType : uint32_t {
+    OTHER = 0,
+    GL = 1,
+    GRAPHICS = 2,
+    MULTIMEDIA = 3,
+    CAMERA = 4,
+    NUM_TYPES,
+};
+
+enum MemtrackStatus : uint32_t {
+    SUCCESS = 0,
+    MEMORY_TRACKING_NOT_SUPPORTED = 1,
+    TYPE_NOT_SUPPORTED = 2,
+};
+
+/* A vector of MemtrackRecord is returned by the function getMemory().
+ * Each record consists of the size of the memory used by the process and
+ * flags indicate the all the MemtrackFlag that are valid for this record.
+ * see getMemory() comments for further details.
+ */
+struct MemtrackRecord {
+    uint64_t sizeInBytes;
+    /*
+     * This is the bitfield for the MemtrackFlag indicating all the flags that
+     * are valid for this record.
+     */
+    uint32_t flags;
+};
diff --git a/memtrack/1.0/vts/Android.mk b/memtrack/1.0/vts/Android.mk
new file mode 100644
index 0000000..397f946
--- /dev/null
+++ b/memtrack/1.0/vts/Android.mk
@@ -0,0 +1,21 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
diff --git a/memtrack/1.0/vts/Memtrack.vts b/memtrack/1.0/vts/Memtrack.vts
new file mode 100644
index 0000000..9fce2a0
--- /dev/null
+++ b/memtrack/1.0/vts/Memtrack.vts
@@ -0,0 +1,33 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IMemtrack"
+
+package: "android.hardware.memtrack"
+
+import: "android.hardware.memtrack@1.0::types"
+
+interface: {
+    api: {
+        name: "getMemory"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::memtrack::V1_0::MemtrackStatus"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::memtrack::V1_0::MemtrackRecord"
+            }
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::memtrack::V1_0::MemtrackType"
+        }
+    }
+
+}
diff --git a/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..b3e560a
--- /dev/null
+++ b/memtrack/1.0/vts/functional/Android.bp
@@ -0,0 +1,40 @@
+//
+// 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_test {
+    name: "memtrack_hidl_hal_test",
+    gtest: true,
+    srcs: ["memtrack_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.memtrack@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
new file mode 100644
index 0000000..597b5da
--- /dev/null
+++ b/memtrack/1.0/vts/functional/memtrack_hidl_hal_test.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "memtrack_hidl_hal_test"
+#include <android-base/logging.h>
+#include <android/hardware/memtrack/1.0/IMemtrack.h>
+
+#include <gtest/gtest.h>
+
+#include <algorithm>
+#include <vector>
+
+using ::android::hardware::memtrack::V1_0::IMemtrack;
+using ::android::hardware::memtrack::V1_0::MemtrackRecord;
+using ::android::hardware::memtrack::V1_0::MemtrackFlag;
+using ::android::hardware::memtrack::V1_0::MemtrackType;
+using ::android::hardware::memtrack::V1_0::MemtrackStatus;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::sp;
+using std::vector;
+using std::count_if;
+
+class MemtrackHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    memtrack = IMemtrack::getService("memtrack");
+    ASSERT_NE(memtrack, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IMemtrack> memtrack;
+};
+
+/* Returns true if flags contains at least min, and no more than max,
+ * of the flags in flagSet. Returns false otherwise.
+ */
+bool rightFlagCount(uint32_t flags, vector<MemtrackFlag> flagSet, uint32_t min,
+                    uint32_t max) {
+  uint32_t count =
+      count_if(flagSet.begin(), flagSet.end(),
+               [&](MemtrackFlag f) { return flags & (uint32_t)f; });
+  return (min <= count && count <= max);
+}
+
+/* Returns true when passed a valid, defined status, false otherwise.
+ */
+bool validStatus(MemtrackStatus s) {
+  vector<MemtrackStatus> statusVec = {
+      MemtrackStatus::SUCCESS, MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED,
+      MemtrackStatus::TYPE_NOT_SUPPORTED};
+  return std::find(statusVec.begin(), statusVec.end(), s) != statusVec.end();
+}
+
+/* Returns a pid found in /proc for which the string read from
+ * /proc/[pid]/cmdline matches cmd, or -1 if no such pid exists.
+ */
+pid_t getPidFromCmd(const char cmd[], uint32_t len) {
+  const char procs[] = "/proc/";
+  DIR *dir = opendir(procs);
+  if (!dir) {
+    return -1;
+  }
+
+  struct dirent *proc;
+  while ((proc = readdir(dir)) != NULL) {
+    if (!isdigit(proc->d_name[0])) {
+      continue;
+    }
+    char line[len];
+    char fname[PATH_MAX];
+    snprintf(fname, PATH_MAX, "/proc/%s/cmdline", proc->d_name);
+
+    FILE *file = fopen(fname, "r");
+    if (!file) {
+      continue;
+    }
+    char *str = fgets(line, len, file);
+    fclose(file);
+    if (!str || strcmp(str, cmd)) {
+      continue;
+    } else {
+      closedir(dir);
+      return atoi(proc->d_name);
+    }
+  }
+  closedir(dir);
+  return -1;
+}
+
+auto generate_cb(MemtrackStatus *s, hidl_vec<MemtrackRecord> *v) {
+  return [=](MemtrackStatus status, hidl_vec<MemtrackRecord> vec) {
+    *s = status;
+    *v = vec;
+  };
+}
+
+/* Sanity check results when getMemory() is passed a negative PID
+ */
+TEST_F(MemtrackHidlTest, BadPidTest) {
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
+       i++) {
+    Return<void> ret =
+        memtrack->getMemory(-1, static_cast<MemtrackType>(i), cb);
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_TRUE(validStatus(s));
+  }
+}
+
+/* Sanity check results when getMemory() is passed a bad memory usage type
+ */
+TEST_F(MemtrackHidlTest, BadTypeTest) {
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  Return<void> ret = memtrack->getMemory(getpid(), MemtrackType::NUM_TYPES, cb);
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(validStatus(s));
+}
+
+/* Call memtrack on the surfaceflinger process and check that the results are
+ * reasonable for all memory types, including valid flag combinations for
+ * every MemtrackRecord returned.
+ */
+TEST_F(MemtrackHidlTest, SurfaceflingerTest) {
+  const char cmd[] = "/system/bin/surfaceflinger";
+  const uint32_t len = sizeof(cmd);
+  pid_t pid = getPidFromCmd(cmd, len);
+  ASSERT_LE(0, pid) << "Surfaceflinger process not found";
+
+  MemtrackStatus s;
+  hidl_vec<MemtrackRecord> v;
+  auto cb = generate_cb(&s, &v);
+  uint32_t unsupportedCount = 0;
+  for (uint32_t i = 0; i < static_cast<uint32_t>(MemtrackType::NUM_TYPES);
+       i++) {
+    Return<void> ret =
+        memtrack->getMemory(pid, static_cast<MemtrackType>(i), cb);
+    ASSERT_TRUE(ret.isOk());
+
+    switch (s) {
+      case MemtrackStatus::MEMORY_TRACKING_NOT_SUPPORTED:
+        unsupportedCount++;
+        break;
+      case MemtrackStatus::TYPE_NOT_SUPPORTED:
+        break;
+      case MemtrackStatus::SUCCESS: {
+        for (uint32_t j = 0; j < v.size(); j++) {
+          // Enforce flag constraints
+          vector<MemtrackFlag> smapFlags = {MemtrackFlag::SMAPS_ACCOUNTED,
+                                            MemtrackFlag::SMAPS_UNACCOUNTED};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, smapFlags, 1, 1));
+          vector<MemtrackFlag> shareFlags = {MemtrackFlag::SHARED,
+                                             MemtrackFlag::SHARED_PSS,
+                                             MemtrackFlag::PRIVATE};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, shareFlags, 0, 1));
+          vector<MemtrackFlag> systemFlags = {MemtrackFlag::SYSTEM,
+                                              MemtrackFlag::DEDICATED};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, systemFlags, 0, 1));
+          vector<MemtrackFlag> secureFlags = {MemtrackFlag::SECURE,
+                                              MemtrackFlag::NONSECURE};
+          EXPECT_TRUE(rightFlagCount(v[j].flags, secureFlags, 0, 1));
+        }
+        break;
+      }
+      default:
+        FAIL();
+    }
+  }
+  // If tracking is not supported this should be returned for all types.
+  ASSERT_TRUE(unsupportedCount == 0 ||
+              unsupportedCount ==
+                  static_cast<uint32_t>(MemtrackType::NUM_TYPES));
+}
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
new file mode 100644
index 0000000..8dcaabb
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalMemtrackHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/memtrack/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..9b00b4c
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Memtrack HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalMemtrackHidlTargetTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            _64bit::DATA/nativetest64/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+    </test>
+</configuration>
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/Android.mk b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..d397621
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalMemtrackHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/memtrack/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/AndroidTest.xml b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..d813be1
--- /dev/null
+++ b/memtrack/1.0/vts/functional/vts/testcases/hal/memtrack/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Memtrack HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalMemtrackHidlTargetProfilingTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            _64bit::DATA/nativetest64/memtrack_hidl_hal_test/memtrack_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/memtrack/1.0/vts/types.vts b/memtrack/1.0/vts/types.vts
new file mode 100644
index 0000000..bec090f
--- /dev/null
+++ b/memtrack/1.0/vts/types.vts
@@ -0,0 +1,121 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.memtrack"
+
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SMAPS_ACCOUNTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "SMAPS_UNACCOUNTED"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "SHARED"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "SHARED_PSS"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "PRIVATE"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "SYSTEM"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "DEDICATED"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "NONSECURE"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "SECURE"
+        scalar_value: {
+            uint32_t: 512
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OTHER"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "GL"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "GRAPHICS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "MULTIMEDIA"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "CAMERA"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "NUM_TYPES"
+        scalar_value: {
+            uint32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "MEMORY_TRACKING_NOT_SUPPORTED"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "TYPE_NOT_SUPPORTED"
+        scalar_value: {
+            uint32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::memtrack::V1_0::MemtrackRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sizeInBytes"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
diff --git a/memtrack/Android.bp b/memtrack/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/memtrack/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/power/1.0/Android.bp b/power/1.0/Android.bp
new file mode 100644
index 0000000..db8c721
--- /dev/null
+++ b/power/1.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.power@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0",
+    srcs: [
+        "types.hal",
+        "IPower.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/types.cpp",
+        "android/hardware/power/1.0/PowerAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.power@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0",
+    srcs: [
+        "types.hal",
+        "IPower.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/types.h",
+        "android/hardware/power/1.0/IPower.h",
+        "android/hardware/power/1.0/IHwPower.h",
+        "android/hardware/power/1.0/BnHwPower.h",
+        "android/hardware/power/1.0/BpHwPower.h",
+        "android/hardware/power/1.0/BsPower.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.power@1.0",
+    generated_sources: ["android.hardware.power@1.0_genc++"],
+    generated_headers: ["android.hardware.power@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.power@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.power.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/power/1.0/ $(genDir)/android/hardware/power/1.0/",
+    srcs: [
+        "types.hal",
+        "IPower.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/types.vts.cpp",
+        "android/hardware/power/1.0/Power.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.power.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/power/1.0/ $(genDir)/android/hardware/power/1.0/",
+    srcs: [
+        "types.hal",
+        "IPower.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/types.vts.h",
+        "android/hardware/power/1.0/Power.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.power.vts.driver@1.0",
+    generated_sources: ["android.hardware.power.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.power.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.power.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.power@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.power@1.0-IPower-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/power/1.0/ $(genDir)/android/hardware/power/1.0/",
+    srcs: [
+        "IPower.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/Power.vts.cpp",
+        "android/hardware/power/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.power@1.0-IPower-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.power@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/power/1.0/ $(genDir)/android/hardware/power/1.0/",
+    srcs: [
+        "IPower.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/power/1.0/Power.vts.h",
+        "android/hardware/power/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.power@1.0-IPower-vts.profiler",
+    generated_sources: ["android.hardware.power@1.0-IPower-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.power@1.0-IPower-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.power@1.0-IPower-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.power@1.0",
+    ],
+}
diff --git a/power/1.0/Android.mk b/power/1.0/Android.mk
new file mode 100644
index 0000000..4e11867
--- /dev/null
+++ b/power/1.0/Android.mk
@@ -0,0 +1,270 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.power@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (Feature)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/Feature.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.Feature
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerHint)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerHint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerHint
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerStatePlatformSleepState)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerStatePlatformSleepState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerStatePlatformSleepState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerStateVoter)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerStateVoter.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerStateVoter
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IPower.hal
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/IPower.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IPower.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::IPower
+
+$(GEN): $(LOCAL_PATH)/IPower.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.power@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (Feature)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/Feature.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.Feature
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerHint)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerHint.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerHint
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerStatePlatformSleepState)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerStatePlatformSleepState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerStatePlatformSleepState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PowerStateVoter)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/PowerStateVoter.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.PowerStateVoter
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IPower.hal
+#
+GEN := $(intermediates)/android/hardware/power/V1_0/IPower.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IPower.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.power@1.0::IPower
+
+$(GEN): $(LOCAL_PATH)/IPower.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/power/1.0/IPower.hal b/power/1.0/IPower.hal
new file mode 100644
index 0000000..6cba42a
--- /dev/null
+++ b/power/1.0/IPower.hal
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+package android.hardware.power@1.0;
+
+/*
+ * Constructor for the interface performs power management setup actions at
+ * runtime startup, such as to set default cpufreq parameters.
+ */
+interface IPower {
+    /*
+     * setInteractive() performs power management actions upon the
+     * system entering interactive state (that is, the system is awake
+     * and ready for interaction, often with UI devices such as
+     * display and touchscreen enabled) or non-interactive state (the
+     * system appears asleep, display usually turned off). The
+     * non-interactive state may be entered after a period of
+     * inactivity in order to conserve battery power during
+     * such inactive periods.
+     *
+     * Typical actions are to turn on or off devices and adjust
+     * cpufreq parameters. This function may also call the
+     * appropriate interfaces to allow the kernel to suspend the
+     * system to low-power sleep state when entering non-interactive
+     * state, and to disallow low-power suspend when the system is in
+     * interactive state. When low-power suspend state is allowed, the
+     * kernel may suspend the system whenever no wakelocks are held.
+     *
+     * For example,
+     * This function can be called to enter non-interactive state after
+     * turning off the screen (if present) and called to enter
+     * interactive state prior to turning on the screen.
+     *
+     * @param interactive is true when the system is transitioning to an
+     * interactive state and false when transitioning to a
+     * non-interactive state.
+     */
+    setInteractive(bool interactive);
+
+    /*
+     * powerHint() is called to pass hints on power requirements which
+     * may result in adjustment of power/performance parameters of the
+     * cpufreq governor and other controls.
+     *
+     * A particular platform may choose to ignore any hint.
+     *
+     * @param hint PowerHint which is passed
+     * @param data contains additional information about the hint
+     * and is described along with the comments for each of the hints.
+     */
+    powerHint(PowerHint hint, int32_t data);
+
+    /*
+     * setFeature() is called to turn on or off a particular feature
+     * depending on the state parameter.
+     *
+     * @param feature Feature which needs to be set
+     * @param activate true/false to enable/disable the feature
+     */
+    setFeature(Feature feature, bool activate);
+
+    /*
+     * Platform-level sleep state stats:
+     * Report cumulative info on the statistics on platform-level sleep states
+     * since boot.
+     *
+     * Higher the index in the returned <states> vector deeper the state is
+     * i.e. lesser steady-state power is consumed by the platform to be
+     * resident in that state.
+     *
+     * @return states of power states the device supports
+     * @return retval SUCCESS on success or FILESYSTEM_ERROR on filesystem
+     * nodes access error.
+     */
+    getPlatformLowPowerStats()
+            generates (vec<PowerStatePlatformSleepState> states, Status retval);
+};
diff --git a/power/1.0/default/Android.bp b/power/1.0/default/Android.bp
new file mode 100644
index 0000000..1a5a897
--- /dev/null
+++ b/power/1.0/default/Android.bp
@@ -0,0 +1,49 @@
+// 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.power@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Power.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.power@1.0",
+    ],
+
+}
+
+cc_binary {
+    relative_install_path: "hw",
+    name: "android.hardware.power@1.0-service",
+    init_rc: ["android.hardware.power@1.0-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libdl",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "android.hardware.power@1.0",
+    ],
+
+}
diff --git a/power/1.0/default/Power.cpp b/power/1.0/default/Power.cpp
new file mode 100644
index 0000000..2ddac0a
--- /dev/null
+++ b/power/1.0/default/Power.cpp
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.power@1.0-impl"
+
+#include <log/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/power.h>
+
+#include "Power.h"
+
+namespace android {
+namespace hardware {
+namespace power {
+namespace V1_0 {
+namespace implementation {
+
+Power::Power(power_module_t *module) : mModule(module) {
+    if (mModule)
+        mModule->init(mModule);
+}
+
+Power::~Power() {
+    delete(mModule);
+}
+
+// Methods from ::android::hardware::power::V1_0::IPower follow.
+Return<void> Power::setInteractive(bool interactive)  {
+    if (mModule->setInteractive)
+        mModule->setInteractive(mModule, interactive ? 1 : 0);
+    return Void();
+}
+
+Return<void> Power::powerHint(PowerHint hint, int32_t data)  {
+    int32_t param = data;
+    if (mModule->powerHint) {
+        if (data)
+            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), &param);
+        else
+            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), NULL);
+    }
+    return Void();
+}
+
+Return<void> Power::setFeature(Feature feature, bool activate)  {
+    if (mModule->setFeature)
+        mModule->setFeature(mModule, static_cast<feature_t>(feature),
+                activate ? 1 : 0);
+    return Void();
+}
+
+Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)  {
+    hidl_vec<PowerStatePlatformSleepState> states;
+    ssize_t number_platform_modes;
+    size_t *voters = nullptr;
+    power_state_platform_sleep_state_t *legacy_states = nullptr;
+    int ret;
+
+    if (mModule->get_number_of_platform_modes == nullptr ||
+            mModule->get_voter_list == nullptr ||
+            mModule->get_platform_low_power_stats == nullptr)
+    {
+        _hidl_cb(states, Status::SUCCESS);
+        return Void();
+    }
+
+    number_platform_modes = mModule->get_number_of_platform_modes(mModule);
+    if (number_platform_modes)
+    {
+       if (SIZE_MAX / sizeof(size_t) <= number_platform_modes)  // overflow
+           goto done;
+       voters = new (std::nothrow) size_t [number_platform_modes];
+       if (voters == nullptr)
+           goto done;
+
+       ret = mModule->get_voter_list(mModule, voters);
+       if (ret != 0)
+           goto done;
+
+       if (SIZE_MAX / sizeof(power_state_platform_sleep_state_t)
+           <= number_platform_modes)  // overflow
+           goto done;
+       legacy_states = new (std::nothrow)
+           power_state_platform_sleep_state_t [number_platform_modes];
+       if (legacy_states == nullptr)
+           goto done;
+
+       for (int i = 0; i < number_platform_modes; i++)
+       {
+          legacy_states[i].voters = nullptr;
+          legacy_states[i].voters = new power_state_voter_t [voters[i]];
+          if (legacy_states[i].voters == nullptr)
+              goto done;
+       }
+
+       ret = mModule->get_platform_low_power_stats(mModule, legacy_states);
+       if (ret != 0)
+           goto done;
+
+       states.resize(number_platform_modes);
+       for (int i = 0; i < number_platform_modes; i++)
+       {
+          power_state_platform_sleep_state_t& legacy_state = legacy_states[i];
+          PowerStatePlatformSleepState& state = states[i];
+          state.name = legacy_state.name;
+          state.residencyInMsecSinceBoot = legacy_state.residency_in_msec_since_boot;
+          state.totalTransitions = legacy_state.total_transitions;
+          state.supportedOnlyInSuspend = legacy_state.supported_only_in_suspend;
+          state.voters.resize(voters[i]);
+          for(size_t j = 0; j < voters[i]; j++)
+          {
+              state.voters[j].name = legacy_state.voters[j].name;
+              state.voters[j].totalTimeInMsecVotedForSinceBoot = legacy_state.voters[j].total_time_in_msec_voted_for_since_boot;
+              state.voters[j].totalNumberOfTimesVotedSinceBoot = legacy_state.voters[j].total_number_of_times_voted_since_boot;
+          }
+       }
+    }
+done:
+    if (legacy_states)
+    {
+        for (int i = 0; i < number_platform_modes; i++)
+        {
+            if(legacy_states[i].voters)
+                delete(legacy_states[i].voters);
+        }
+    }
+    delete[] legacy_states;
+    delete[] voters;
+    _hidl_cb(states, Status::SUCCESS);
+    return Void();
+}
+
+IPower* HIDL_FETCH_IPower(const char* /* name */) {
+    int ret = 0;
+    const hw_module_t* hw_module = NULL;
+    power_module_t *power_module;
+    ret = hw_get_module(POWER_HARDWARE_MODULE_ID, &hw_module);
+    if (ret == 0 && hw_module->methods->open) {
+        ret = hw_module->methods->open(hw_module, POWER_HARDWARE_MODULE_ID,
+                reinterpret_cast<hw_device_t**>(&power_module));
+        if (ret == 0) {
+            return new Power(power_module);
+        }
+        else {
+            ALOGE("Passthrough failed to load legacy power HAL.");
+            return nullptr;
+        }
+    }
+    else {
+        ALOGE ("hw_get_module %s failed: %d", POWER_HARDWARE_MODULE_ID, ret);
+        return nullptr;
+    }
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
diff --git a/power/1.0/default/Power.h b/power/1.0/default/Power.h
new file mode 100644
index 0000000..a43aefb
--- /dev/null
+++ b/power/1.0/default/Power.h
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_POWER_V1_0_POWER_H
+#define ANDROID_HARDWARE_POWER_V1_0_POWER_H
+
+#include <android/hardware/power/1.0/IPower.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace power {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::power::V1_0::Feature;
+using ::android::hardware::power::V1_0::IPower;
+using ::android::hardware::power::V1_0::PowerHint;
+using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
+using ::android::hardware::power::V1_0::Status;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Power : public IPower {
+    Power(power_module_t* module);
+    ~Power();
+    Return<void> setInteractive(bool interactive)  override;
+    Return<void> powerHint(PowerHint hint, int32_t data)  override;
+    Return<void> setFeature(Feature feature, bool activate)  override;
+    Return<void> getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)  override;
+
+  private:
+    power_module_t* mModule;
+};
+
+extern "C" IPower* HIDL_FETCH_IPower(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace power
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_POWER_V1_0_POWER_H
diff --git a/power/1.0/default/android.hardware.power@1.0-service.rc b/power/1.0/default/android.hardware.power@1.0-service.rc
new file mode 100644
index 0000000..6063541
--- /dev/null
+++ b/power/1.0/default/android.hardware.power@1.0-service.rc
@@ -0,0 +1,4 @@
+service power-hal-1-0 /system/bin/hw/android.hardware.power@1.0-service
+    class hal
+    user system
+    group system
diff --git a/power/1.0/default/service.cpp b/power/1.0/default/service.cpp
new file mode 100644
index 0000000..e8618b8
--- /dev/null
+++ b/power/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.power@1.0-service"
+
+#include <android/hardware/power/1.0/IPower.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::power::V1_0::IPower;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IPower>();
+}
diff --git a/power/1.0/types.hal b/power/1.0/types.hal
new file mode 100644
index 0000000..c27242e
--- /dev/null
+++ b/power/1.0/types.hal
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+package android.hardware.power@1.0;
+
+/* Power hint identifiers passed to powerHint() */
+enum PowerHint : uint32_t {
+   /*
+    * Foreground app has started or stopped requesting a VSYNC pulse
+    * from SurfaceFlinger. If the app has started requesting VSYNC
+    * then CPU and GPU load is expected soon, and it may be appropriate
+    * to raise speeds of CPU, memory bus, etc. The data parameter is
+    * non-zero to indicate VSYNC pulse is now requested, or zero for
+    * VSYNC pulse no longer requested.
+    */
+    VSYNC = 0x00000001,
+
+
+   /*
+    * User is interacting with the device, for example, touchscreen
+    * events are incoming. CPU and GPU load may be expected soon,
+    * and it may be appropriate to raise speeds of CPU, memory bus,
+    * etc. The data parameter is the estimated length of the interaction
+    * in milliseconds, or 0 if unknown.
+    */
+    INTERACTION = 0x00000002,
+
+
+    /* DO NOT USE VIDEO_ENCODE/_DECODE!  They will be removed in
+     * KLP.
+     */
+    VIDEO_ENCODE = 0x00000003,
+    VIDEO_DECODE = 0x00000004,
+
+   /*
+    * Low power mode is activated or deactivated. Low power mode
+    * is intended to save battery at the cost of performance. The data
+    * parameter is non-zero when low power mode is activated, and zero
+    * when deactivated.
+    */
+    LOW_POWER = 0x00000005,
+
+   /*
+    * Sustained Performance mode is actived or deactivated. Sustained
+    * performance mode is intended to provide a consistent level of
+    * performance for a prolonged amount of time. The data parameter is
+    * non-zero when sustained performance mode is activated, and zero
+    * when deactivated.
+    */
+    SUSTAINED_PERFORMANCE = 0x00000006,
+
+   /*
+    * VR Mode is activated or deactivated. VR mode is intended to
+    * provide minimum guarantee for performance for the amount of time the
+    * device can sustain it. The data parameter is non-zero when the mode
+    * is activated and zero when deactivated.
+    */
+    VR_MODE = 0x00000007,
+
+   /*
+    * This hint indicates that an application has been launched. Can be used
+    * for device specific optimizations during application launch. The data
+    * parameter is non-zero when the application starts to launch and zero when
+    * it has been launched.
+    */
+    LAUNCH = 0x00000008,
+
+   /*
+    * When device enters some special modes, e.g. theater mode in Android
+    * Wear, there is no touch interaction expected between device and user.
+    * Touch controller could be disabled in those modes to save power.
+    * The data parameter is non-zero when touch could be disabled, and zero
+    * when touch needs to be re-enabled.
+    */
+    DISABLE_TOUCH = 0x00000009
+};
+
+enum Feature : uint32_t {
+    /*
+     * Enabling/Disabling this feature will allow/disallow the system
+     * to wake up by tapping the screen twice.
+     */
+    POWER_FEATURE_DOUBLE_TAP_TO_WAKE = 0x00000001
+};
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+    FILESYSTEM_ERROR = 1
+};
+/*
+ * Platform-level sleep state stats:
+ * PowerStateVoter struct is useful for describing the individual voters
+ * when a Platform-level sleep state is chosen by aggregation of votes from
+ * multiple clients/system conditions.
+ *
+ * This helps in attirbuting what in the device is blocking the device from
+ * entering the lowest Platform-level sleep state.
+ */
+struct PowerStateVoter {
+    /*
+     * Name of the voter.
+     */
+     string name;
+
+    /*
+     * Total time in msec the voter voted for the platform sleep state since
+     * boot.
+     */
+     uint64_t totalTimeInMsecVotedForSinceBoot;
+
+    /*
+     * Number of times the voter voted for the platform sleep state since boot.
+     */
+     uint64_t totalNumberOfTimesVotedSinceBoot;
+};
+
+/*
+ * Platform-level sleep state stats:
+ * PowerStatePlatformSleepState represents the Platform-level sleep state
+ * the device is capable of getting into.
+ *
+ * SoCs usually have more than one Platform-level sleep state.
+ */
+struct PowerStatePlatformSleepState {
+    /*
+     * Platform-level Sleep state name.
+     */
+    string name;
+
+    /*
+     * Time spent in msec at this platform-level sleep state since boot.
+     */
+    uint64_t residencyInMsecSinceBoot;
+
+    /*
+     * Total number of times system entered this state.
+     */
+    uint64_t totalTransitions;
+
+    /*
+     * This platform-level sleep state can only be reached during system suspend
+     */
+    bool supportedOnlyInSuspend;
+
+    /*
+     * voters is useful if the Platform-level sleep state
+     * is chosen by aggregation votes from multiple clients/system conditions.
+     * All the voters have to say yes or all the system conditions need to be
+     * met to enter a platform-level sleep state.
+     *
+     * Vector of size zero implies either the info is not available
+     * or the system does not follow a voting mechanism to choose this
+     * Platform-level sleep state.
+     */
+    vec<PowerStateVoter> voters;
+};
diff --git a/power/1.0/vts/Android.mk b/power/1.0/vts/Android.mk
new file mode 100644
index 0000000..df5dac8
--- /dev/null
+++ b/power/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/power/1.0/vts/Power.vts b/power/1.0/vts/Power.vts
new file mode 100644
index 0000000..1711290
--- /dev/null
+++ b/power/1.0/vts/Power.vts
@@ -0,0 +1,57 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IPower"
+
+package: "android.hardware.power"
+
+import: "android.hardware.power@1.0::types"
+
+interface: {
+    api: {
+        name: "setInteractive"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "powerHint"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::power::V1_0::PowerHint"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setFeature"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::power::V1_0::Feature"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getPlatformLowPowerStats"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::power::V1_0::PowerStatePlatformSleepState"
+            }
+        }
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::power::V1_0::Status"
+        }
+    }
+
+}
diff --git a/power/1.0/vts/functional/Android.bp b/power/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..81dc316
--- /dev/null
+++ b/power/1.0/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+//
+// 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_test {
+    name: "power_hidl_hal_test",
+    gtest: true,
+    srcs: ["power_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.power@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/power/1.0/vts/functional/Android.mk b/power/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/power_hidl_hal_test.cpp b/power/1.0/vts/functional/power_hidl_hal_test.cpp
new file mode 100644
index 0000000..3f0ef56
--- /dev/null
+++ b/power/1.0/vts/functional/power_hidl_hal_test.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "power_hidl_hal_test"
+#include <android-base/logging.h>
+
+#include <cutils/properties.h>
+
+#include <android/hardware/power/1.0/IPower.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::power::V1_0::IPower;
+using ::android::hardware::power::V1_0::Feature;
+using ::android::hardware::power::V1_0::PowerHint;
+using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
+using ::android::hardware::power::V1_0::Status;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::sp;
+
+class PowerHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    power = IPower::getService();
+    ASSERT_NE(power, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IPower> power;
+};
+
+// Sanity check Power::setInteractive.
+TEST_F(PowerHidlTest, SetInteractive) {
+  Return<void> ret;
+
+  ret = power->setInteractive(true);
+  ASSERT_TRUE(ret.isOk());
+
+  ret = power->setInteractive(false);
+  ASSERT_TRUE(ret.isOk());
+}
+
+// Sanity check Power::powerHint on good and bad inputs.
+TEST_F(PowerHidlTest, PowerHint) {
+  PowerHint badHint = static_cast<PowerHint>(0xA);
+  auto hints = {PowerHint::VSYNC,         PowerHint::INTERACTION,
+                PowerHint::VIDEO_ENCODE,  PowerHint::VIDEO_DECODE,
+                PowerHint::LOW_POWER,     PowerHint::SUSTAINED_PERFORMANCE,
+                PowerHint::VR_MODE,       PowerHint::LAUNCH,
+                PowerHint::DISABLE_TOUCH, badHint};
+  Return<void> ret;
+  for (auto hint : hints) {
+    ret = power->powerHint(hint, 1);
+    ASSERT_TRUE(ret.isOk());
+
+    ret = power->powerHint(hint, 0);
+    ASSERT_TRUE(ret.isOk());
+  }
+}
+
+// Sanity check Power::setFeature() on good and bad inputs.
+TEST_F(PowerHidlTest, SetFeature) {
+  Return<void> ret;
+  ret = power->setFeature(Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, true);
+  ASSERT_TRUE(ret.isOk());
+  ret = power->setFeature(Feature::POWER_FEATURE_DOUBLE_TAP_TO_WAKE, false);
+  ASSERT_TRUE(ret.isOk());
+
+  Feature badFeature = static_cast<Feature>(0x2);
+  ret = power->setFeature(badFeature, true);
+  ASSERT_TRUE(ret.isOk());
+  ret = power->setFeature(badFeature, false);
+  ASSERT_TRUE(ret.isOk());
+}
+
+// Sanity check Power::getPlatformLowPowerStats().
+TEST_F(PowerHidlTest, GetPlatformLowPowerStats) {
+  hidl_vec<PowerStatePlatformSleepState> vec;
+  Status s;
+  auto cb = [&vec, &s](hidl_vec<PowerStatePlatformSleepState> states,
+                       Status status) {
+    vec = states;
+    s = status;
+  };
+  Return<void> ret = power->getPlatformLowPowerStats(cb);
+  ASSERT_TRUE(ret.isOk());
+  ASSERT_TRUE(s == Status::SUCCESS || s == Status::FILESYSTEM_ERROR);
+}
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/power/1.0/vts/functional/vts/Android.mk b/power/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/vts/testcases/Android.mk b/power/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/vts/testcases/hal/Android.mk b/power/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/Android.mk b/power/1.0/vts/functional/vts/testcases/hal/power/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/__init__.py b/power/1.0/vts/functional/vts/testcases/hal/power/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/__init__.py
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/Android.mk b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/Android.mk b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/Android.mk
new file mode 100644
index 0000000..c66b6fb
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalPowerHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/power/hidl/target
+include test/vts/tools/build/Android.host_config.mk
+
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..bb80de2
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Power HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalPowerHidlTargetTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/power_hidl_hal_test/power_hidl_hal_test,
+            _64bit::DATA/nativetest64/power_hidl_hal_test/power_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/Android.mk b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..6f9e399
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalPowerHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/power/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
+
diff --git a/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/AndroidTest.xml b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..263086c
--- /dev/null
+++ b/power/1.0/vts/functional/vts/testcases/hal/power/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Power HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalPowerHidlTargetProfilingTest"/>
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/power_hidl_hal_test/power_hidl_hal_test,
+            _64bit::DATA/nativetest64/power_hidl_hal_test/power_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/power/1.0/vts/types.vts b/power/1.0/vts/types.vts
new file mode 100644
index 0000000..94c003b
--- /dev/null
+++ b/power/1.0/vts/types.vts
@@ -0,0 +1,133 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.power"
+
+
+attribute: {
+    name: "::android::hardware::power::V1_0::PowerHint"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "VSYNC"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "INTERACTION"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "VIDEO_ENCODE"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "VIDEO_DECODE"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "LOW_POWER"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "SUSTAINED_PERFORMANCE"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "VR_MODE"
+        scalar_value: {
+            uint32_t: 7
+        }
+        enumerator: "LAUNCH"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "DISABLE_TOUCH"
+        scalar_value: {
+            uint32_t: 9
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::power::V1_0::Feature"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "POWER_FEATURE_DOUBLE_TAP_TO_WAKE"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::power::V1_0::Status"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "FILESYSTEM_ERROR"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::power::V1_0::PowerStateVoter"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "totalTimeInMsecVotedForSinceBoot"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "totalNumberOfTimesVotedSinceBoot"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::power::V1_0::PowerStatePlatformSleepState"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "residencyInMsecSinceBoot"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "totalTransitions"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "supportedOnlyInSuspend"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "voters"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::power::V1_0::PowerStateVoter"
+        }
+    }
+}
+
diff --git a/power/Android.bp b/power/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/power/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index e9eb10e..e17d949 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -86,3 +86,302 @@
         "android.hidl.base@1.0",
     ],
 }
+
+genrule {
+    name: "android.hardware.radio.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "types.hal",
+        "IRadio.hal",
+        "IRadioIndication.hal",
+        "IRadioResponse.hal",
+        "ISap.hal",
+        "ISapCallback.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/types.vts.cpp",
+        "android/hardware/radio/1.0/Radio.vts.cpp",
+        "android/hardware/radio/1.0/RadioIndication.vts.cpp",
+        "android/hardware/radio/1.0/RadioResponse.vts.cpp",
+        "android/hardware/radio/1.0/Sap.vts.cpp",
+        "android/hardware/radio/1.0/SapCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "types.hal",
+        "IRadio.hal",
+        "IRadioIndication.hal",
+        "IRadioResponse.hal",
+        "ISap.hal",
+        "ISapCallback.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/types.vts.h",
+        "android/hardware/radio/1.0/Radio.vts.h",
+        "android/hardware/radio/1.0/RadioIndication.vts.h",
+        "android/hardware/radio/1.0/RadioResponse.vts.h",
+        "android/hardware/radio/1.0/Sap.vts.h",
+        "android/hardware/radio/1.0/SapCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio.vts.driver@1.0",
+    generated_sources: ["android.hardware.radio.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.radio.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadio-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadio.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/Radio.vts.cpp",
+        "android/hardware/radio/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadio-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadio.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/Radio.vts.h",
+        "android/hardware/radio/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio@1.0-IRadio-vts.profiler",
+    generated_sources: ["android.hardware.radio@1.0-IRadio-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.radio@1.0-IRadio-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio@1.0-IRadio-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadioIndication-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadioIndication.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/RadioIndication.vts.cpp",
+        "android/hardware/radio/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadioIndication-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadioIndication.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/RadioIndication.vts.h",
+        "android/hardware/radio/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio@1.0-IRadioIndication-vts.profiler",
+    generated_sources: ["android.hardware.radio@1.0-IRadioIndication-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.radio@1.0-IRadioIndication-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio@1.0-IRadioIndication-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadioResponse-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadioResponse.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/RadioResponse.vts.cpp",
+        "android/hardware/radio/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-IRadioResponse-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "IRadioResponse.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/RadioResponse.vts.h",
+        "android/hardware/radio/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio@1.0-IRadioResponse-vts.profiler",
+    generated_sources: ["android.hardware.radio@1.0-IRadioResponse-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.radio@1.0-IRadioResponse-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio@1.0-IRadioResponse-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-ISap-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "ISap.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/Sap.vts.cpp",
+        "android/hardware/radio/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-ISap-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "ISap.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/Sap.vts.h",
+        "android/hardware/radio/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio@1.0-ISap-vts.profiler",
+    generated_sources: ["android.hardware.radio@1.0-ISap-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.radio@1.0-ISap-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio@1.0-ISap-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-ISapCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "ISapCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/SapCallback.vts.cpp",
+        "android/hardware/radio/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.radio@1.0-ISapCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.radio@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/radio/1.0/ $(genDir)/android/hardware/radio/1.0/",
+    srcs: [
+        "ISapCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/radio/1.0/SapCallback.vts.h",
+        "android/hardware/radio/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.radio@1.0-ISapCallback-vts.profiler",
+    generated_sources: ["android.hardware.radio@1.0-ISapCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.radio@1.0-ISapCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.radio@1.0-ISapCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.radio@1.0",
+    ],
+}
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index 941a59e..593dc92 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -109,8 +109,8 @@
     INVALID_SMSC_ADDRESS = 58,            // SMSC address specified is invalid
     NO_SUCH_ENTRY = 59,                   // No such entry present to perform the request
     NETWORK_NOT_READY = 60,               // Network is not ready to perform the request
-    NOT_PROVISIONED = 61,                 // Device doesnot have this value provisioned
-    NO_SUBSCRIPTION = 62,                 // Device doesnot have subscription
+    NOT_PROVISIONED = 61,                 // Device does not have this value provisioned
+    NO_SUBSCRIPTION = 62,                 // Device does not have subscription
     NO_NETWORK_FOUND = 63,                // Network cannot be found
     DEVICE_IN_USE = 64,                   // Operation cannot be performed because the device
                                           // is currently in use
@@ -223,7 +223,7 @@
     RUIM_CORPORATE,
     RUIM_SERVICE_PROVIDER,
     RUIM_RUIM,
-    RUIM_NETWORK1_PUK,                   // The corresponding perso lock is blocked
+    RUIM_NETWORK1_PUK,                    // The corresponding perso lock is blocked
     RUIM_NETWORK2_PUK,
     RUIM_HRPD_PUK,
     RUIM_CORPORATE_PUK,
@@ -232,7 +232,7 @@
 };
 
 enum RadioState : int32_t {
-    OFF = 0,                              // Radio explictly powered off (eg CFUN=0)
+    OFF = 0,                              // Radio explicitly powered off (eg CFUN=0)
     UNAVAILABLE = 1,                      // Radio unavailable (eg, resetting or not booted)
     ON = 10,                              // Radio is ON
 };
@@ -242,17 +242,17 @@
     CONNECT_FAILURE,
     MSG_SIZE_TOO_LARGE,
     MSG_SIZE_TOO_SMALL,
-    CONNECT_OK_CALL_ONGOING
+    CONNECT_OK_CALL_ONGOING,
 };
 
 enum SapDisconnectType : int32_t {
     GRACEFUL,
-    IMMEDIATE
+    IMMEDIATE,
 };
 
 enum SapApduType : int32_t {
     APDU,
-    APDU7816
+    APDU7816,
 };
 
 enum SapResultCode : int32_t {
@@ -263,7 +263,7 @@
     CARD_REMOVED,
     CARD_ALREADY_POWERED_ON,
     DATA_NOT_AVAILABLE,
-    NOT_SUPPORTED
+    NOT_SUPPORTED,
 };
 
 enum SapStatus : int32_t {
@@ -272,21 +272,21 @@
     CARD_NOT_ACCESSIBLE,
     CARD_REMOVED,
     CARD_INSERTED,
-    RECOVERED
+    RECOVERED,
 };
 
 enum SapTransferProtocol : int32_t {
     T0,
-    T1
+    T1,
 };
 
 enum CallState : int32_t {
     ACTIVE,
     HOLDING,
-    DIALING,                             // MO call only
-    ALERTING,                            // MO call only
-    INCOMING,                            // MT call only
-    WAITING,                             // MT call only
+    DIALING,                              // MO call only
+    ALERTING,                             // MO call only
+    INCOMING,                             // MT call only
+    WAITING,                              // MT call only
 };
 
 /*
@@ -311,7 +311,7 @@
     USP,                                  // User specified protocol
     OSIHLP,                               // OSI higher layer protocol
     X244,                                 // X.244
-    RMCF,                                 // Reserved for system mangement convergence function
+    RMCF,                                 // Reserved for system management convergence function
     IA5C,                                 // IA5 characters
 };
 
@@ -323,9 +323,9 @@
 };
 
 enum Clir : int32_t {
-    DEFAULT,                               // "use subscription default value"
-    INVOCATION,                            // restrict CLI presentation
-    SUPPRESSION,                           // allow CLI presentation
+    DEFAULT,                              // "use subscription default value"
+    INVOCATION,                           // restrict CLI presentation
+    SUPPRESSION,                          // allow CLI presentation
 };
 
 enum LastCallFailCause : int32_t {
@@ -519,7 +519,7 @@
                                           // emergency calls are enabled.
     REG_DENIED_EM,                        // Same as REG_DENIED but indicates that
                                           // emergency calls are enabled.
-    UNKNOWN_EM                            // Same as UNKNOWN but indicates that
+    UNKNOWN_EM,                           // Same as UNKNOWN but indicates that
                                           // emergency calls are enabled.
 };
 
@@ -539,8 +539,8 @@
     EVDO_B = 12,
     EHRPD = 13,
     LTE = 14,
-    HSPAP = 15,                            // HSPA+
-    GSM = 16,                              // Only supports voice
+    HSPAP = 15,                           // HSPA+
+    GSM = 16,                             // Only supports voice
     TD_SCDMA = 17,
     IWLAN = 18,
     LTE_CA = 19,
@@ -557,7 +557,7 @@
 };
 
 enum SmsAcknowledgeFailCause : int32_t {
-    MEMORY_CAPAPCITY_EXCEEDED = 0xD3,
+    MEMORY_CAPACITY_EXCEEDED = 0xD3,
     UNSPECIFIED_ERROR = 0XFF,
 };
 
@@ -572,7 +572,7 @@
 enum ClipStatus : int32_t {
     CLIP_PROVISIONED,                     // CLIP provisioned
     CLIP_UNPROVISIONED,                   // CLIP not provisioned
-    UNKOWN,                               // unknown, e.g. no network etc
+    UNKNOWN,                              // unknown, e.g. no network etc
 };
 
 enum SmsWriteArgsStatus : int32_t {
@@ -659,63 +659,63 @@
 
 enum NvItem : int32_t {
     // CDMA radio and account information (items 1-10)
-    CDMA_MEID = 1,                       // CDMA MEID (hex)
-    CDMA_MIN = 2,                        // CDMA MIN (MSID)
-    CDMA_MDN = 3,                        // CDMA MDN
-    CDMA_ACCOLC = 4,                     // CDMA access overload control
+    CDMA_MEID = 1,                        // CDMA MEID (hex)
+    CDMA_MIN = 2,                         // CDMA MIN (MSID)
+    CDMA_MDN = 3,                         // CDMA MDN
+    CDMA_ACCOLC = 4,                      // CDMA access overload control
 
     // Carrier device provisioning (items 11-30)
-    DEVICE_MSL = 11,                     // device MSL
-    RTN_RECONDITIONED_STATUS = 12,       // RTN reconditioned status
-    RTN_ACTIVATION_DATE = 13,            // RTN activation date
-    RTN_LIFE_TIMER = 14,                 // RTN life timer
-    RTN_LIFE_CALLS = 15,                 // RTN life calls
-    RTN_LIFE_DATA_TX = 16,               // RTN life data TX
-    RTN_LIFE_DATA_RX = 17,               // RTN life data RX
-    OMADM_HFA_LEVEL = 18,                // HFA in progress
+    DEVICE_MSL = 11,                      // device MSL
+    RTN_RECONDITIONED_STATUS = 12,        // RTN reconditioned status
+    RTN_ACTIVATION_DATE = 13,             // RTN activation date
+    RTN_LIFE_TIMER = 14,                  // RTN life timer
+    RTN_LIFE_CALLS = 15,                  // RTN life calls
+    RTN_LIFE_DATA_TX = 16,                // RTN life data TX
+    RTN_LIFE_DATA_RX = 17,                // RTN life data RX
+    OMADM_HFA_LEVEL = 18,                 // HFA in progress
 
     // Mobile IP profile information (items 31-50)
-    MIP_PROFILE_NAI = 31,                // NAI realm
-    MIP_PROFILE_HOME_ADDRESS = 32,       // MIP home address
-    MIP_PROFILE_AAA_AUTH = 33,           // AAA auth
-    MIP_PROFILE_HA_AUTH = 34,            // HA auth
-    MIP_PROFILE_PRI_HA_ADDR = 35,        // primary HA address
-    MIP_PROFILE_SEC_HA_ADDR = 36,        // secondary HA address
-    MIP_PROFILE_REV_TUN_PREF = 37,       // reverse TUN preference
-    MIP_PROFILE_HA_SPI = 38,             // HA SPI
-    MIP_PROFILE_AAA_SPI = 39,            // AAA SPI
-    MIP_PROFILE_MN_HA_SS = 40,           // HA shared secret
-    MIP_PROFILE_MN_AAA_SS = 41,          // AAA shared secret
+    MIP_PROFILE_NAI = 31,                 // NAI realm
+    MIP_PROFILE_HOME_ADDRESS = 32,        // MIP home address
+    MIP_PROFILE_AAA_AUTH = 33,            // AAA auth
+    MIP_PROFILE_HA_AUTH = 34,             // HA auth
+    MIP_PROFILE_PRI_HA_ADDR = 35,         // primary HA address
+    MIP_PROFILE_SEC_HA_ADDR = 36,         // secondary HA address
+    MIP_PROFILE_REV_TUN_PREF = 37,        // reverse TUN preference
+    MIP_PROFILE_HA_SPI = 38,              // HA SPI
+    MIP_PROFILE_AAA_SPI = 39,             // AAA SPI
+    MIP_PROFILE_MN_HA_SS = 40,            // HA shared secret
+    MIP_PROFILE_MN_AAA_SS = 41,           // AAA shared secret
 
     // CDMA network and band config (items 51-70)
-    CDMA_PRL_VERSION = 51,               // CDMA PRL version
-    CDMA_BC10 = 52,                      // CDMA band class 10
-    CDMA_BC14 = 53,                      // CDMA band class 14
-    CDMA_SO68 = 54,                      // CDMA SO68
-    CDMA_SO73_COP0 = 55,                 // CDMA SO73 COP0
-    CDMA_SO73_COP1TO7 = 56,              // CDMA SO73 COP1-7
-    CDMA_1X_ADVANCED_ENABLED = 57,       // CDMA 1X Advanced enabled
-    CDMA_EHRPD_ENABLED = 58,             // CDMA eHRPD enabled
-    CDMA_EHRPD_FORCED = 59,              // CDMA eHRPD forced
+    CDMA_PRL_VERSION = 51,                // CDMA PRL version
+    CDMA_BC10 = 52,                       // CDMA band class 10
+    CDMA_BC14 = 53,                       // CDMA band class 14
+    CDMA_SO68 = 54,                       // CDMA SO68
+    CDMA_SO73_COP0 = 55,                  // CDMA SO73 COP0
+    CDMA_SO73_COP1TO7 = 56,               // CDMA SO73 COP1-7
+    CDMA_1X_ADVANCED_ENABLED = 57,        // CDMA 1X Advanced enabled
+    CDMA_EHRPD_ENABLED = 58,              // CDMA eHRPD enabled
+    CDMA_EHRPD_FORCED = 59,               // CDMA eHRPD forced
 
     // LTE network and band config (items 71-90)
-    LTE_BAND_ENABLE_25 = 71,             // LTE band 25 enable
-    LTE_BAND_ENABLE_26 = 72,             // LTE band 26 enable
-    LTE_BAND_ENABLE_41 = 73,             // LTE band 41 enable
+    LTE_BAND_ENABLE_25 = 71,              // LTE band 25 enable
+    LTE_BAND_ENABLE_26 = 72,              // LTE band 26 enable
+    LTE_BAND_ENABLE_41 = 73,              // LTE band 41 enable
 
-    LTE_SCAN_PRIORITY_25 = 74,           // LTE band 25 scan priority
-    LTE_SCAN_PRIORITY_26 = 75,           // LTE band 26 scan priority
-    LTE_SCAN_PRIORITY_41 = 76,           // LTE band 41 scan priority
+    LTE_SCAN_PRIORITY_25 = 74,            // LTE band 25 scan priority
+    LTE_SCAN_PRIORITY_26 = 75,            // LTE band 26 scan priority
+    LTE_SCAN_PRIORITY_41 = 76,            // LTE band 41 scan priority
 
-    LTE_HIDDEN_BAND_PRIORITY_25 = 77,    // LTE hidden band 25 priority
-    LTE_HIDDEN_BAND_PRIORITY_26 = 78,    // LTE hidden band 26 priority
-    LTE_HIDDEN_BAND_PRIORITY_41 = 79,    // LTE hidden band 41 priority
+    LTE_HIDDEN_BAND_PRIORITY_25 = 77,     // LTE hidden band 25 priority
+    LTE_HIDDEN_BAND_PRIORITY_26 = 78,     // LTE hidden band 26 priority
+    LTE_HIDDEN_BAND_PRIORITY_41 = 79,     // LTE hidden band 41 priority
 };
 
 enum ResetNvType : int32_t {
-    RELOAD,                              // reload all NV items
-    ERASE,                               // erase NV reset (SCRTN)
-    FACORY_RESET,                        // factory reset (RTN)
+    RELOAD,                               // reload all NV items
+    ERASE,                                // erase NV reset (SCRTN)
+    FACTORY_RESET,                        // factory reset (RTN)
 };
 
 enum HardwareConfigType : int32_t {
@@ -736,11 +736,11 @@
 };
 
 enum CarrierMatchType : int32_t {
-    ALL = 0,                               // Apply to all carriers with the same mcc/mnc
-    SPN = 1,                               // Use SPN and mcc/mnc to identify the carrier
-    IMSI_PREFIX = 2,                       // Use IMSI prefix and mcc/mnc to identify the carrier
-    GID1 = 3,                              // Use GID1 and mcc/mnc to identify the carrier
-    GID2 = 4,                              // Use GID2 and mcc/mnc to identify the carrier
+    ALL = 0,                              // Apply to all carriers with the same mcc/mnc
+    SPN = 1,                              // Use SPN and mcc/mnc to identify the carrier
+    IMSI_PREFIX = 2,                      // Use IMSI prefix and mcc/mnc to identify the carrier
+    GID1 = 3,                             // Use GID1 and mcc/mnc to identify the carrier
+    GID2 = 4,                             // Use GID2 and mcc/mnc to identify the carrier
 };
 
 struct NeighboringCell {
@@ -804,8 +804,8 @@
 };
 
 enum CdmaSmsSubaddressType : int32_t {
-    NSAP,                                // CCITT X.213 or ISO 8348 AD2
-    USER_SPECIFIED,                      // e.g. X.25
+    NSAP,                                 // CCITT X.213 or ISO 8348 AD2
+    USER_SPECIFIED,                       // e.g. X.25
 };
 
 enum CdmaSmsErrorClass : int32_t {
@@ -849,30 +849,30 @@
 };
 
 enum RadioCapabilityPhase : int32_t {
-    CONFIGURED = 0,                      // Logical Modem's (LM)  initial value
-                                         // and value after FINISH completes
-    START      = 1,                      // START is sent before APPLY and indicates that an
-                                         // APPLY is forthcoming with these same parameters
-    APPLY      = 2,                      // APPLY is sent after all LM's receive START and returned
-                                         // RadioCapability.status = 0. If any START's fail, hal
-                                         // implementation must not send APPLY.
-    UNSOL_RSP  = 3,                      // UNSOL_RSP is sent with unsol radioCapability()
-    FINISH     = 4                       // FINISH is sent after all commands have completed. If an
-                                         // error occurs in any previous command, the
-                                         // RadioAccessesFamily and logicalModemUuid fields must be
-                                         // the prior configuration thus restoring the configuration
-                                         // to the previous value. An error returned by FINISH
-                                         // will generally be ignored or may cause that logical
-                                         // modem to be removed from service.
+    CONFIGURED = 0,                       // Logical Modem's (LM)  initial value
+                                          // and value after FINISH completes
+    START      = 1,                       // START is sent before APPLY and indicates that an
+                                          // APPLY is forthcoming with these same parameters
+    APPLY      = 2,                       // APPLY is sent after all LM's receive START and returned
+                                          // RadioCapability.status = 0. If any START's fail, hal
+                                          // implementation must not send APPLY.
+    UNSOL_RSP  = 3,                       // UNSOL_RSP is sent with unsolicited radioCapability()
+    FINISH     = 4                        // FINISH is sent after all commands have completed. If an
+                                          // error occurs in any previous command, the
+                                          // RadioAccessesFamily and logicalModemUuid fields must be
+                                          // the prior configuration thus restoring the
+                                          // configuration to the previous value. An error returned
+                                          // by FINISH will generally be ignored or may cause that
+                                          // logical modem to be removed from service.
 };
 
 enum RadioCapabilityStatus : int32_t {
-    NONE       = 0,                      // This parameter has no meaning with
-                                         // RadioCapabilityPhase:START, RadioCapabilityPhase:APPLY
-    SUCCESS    = 1,                      // Tell modem the action transaction of set radio
-                                         // capability was success with RadioCapabilityPhase:FINISH
-    FAIL       = 2,                      // Tell modem the action transaction of set radio
-                                         // capability is fail with RadioCapabilityPhase:FINISH.
+    NONE       = 0,                       // This parameter has no meaning with
+                                          // RadioCapabilityPhase:START, RadioCapabilityPhase:APPLY
+    SUCCESS    = 1,                       // Tell modem the action transaction of set radio
+                                          // capability was success with RadioCapabilityPhase:FINISH
+    FAIL       = 2,                       // Tell modem the action transaction of set radio
+                                          // capability is fail with RadioCapabilityPhase:FINISH.
 };
 
 enum RadioAccessFamily : int32_t {
@@ -898,19 +898,19 @@
 };
 
 enum UssdModeType : int32_t {
-    NOTIFY,                                // USSD-Notify
-    REQUEST,                               // USSD-Request
-    NW_RELEASE,                            // Session terminated by network
-    LOCAL_CLIENT,                          // other local client (eg, SIM Toolkit) has responded
-    NOT_SUPPORTED,                         // Operation not supported
-    NW_TIMEOUT,                            // Network timeout
+    NOTIFY,                               // USSD-Notify
+    REQUEST,                              // USSD-Request
+    NW_RELEASE,                           // Session terminated by network
+    LOCAL_CLIENT,                         // other local client (eg, SIM Toolkit) has responded
+    NOT_SUPPORTED,                        // Operation not supported
+    NW_TIMEOUT,                           // Network timeout
 };
 
 enum SimRefreshType : int32_t {
-    SIM_FILE_UPDATE = 0,                   // A file on SIM has been updated.
-    SIM_INIT = 1,                          // SIM initialized. All files should be re-read.
-    SIM_RESET = 2                          // SIM reset. SIM power required, SIM may be locked a
-                                           // nd all files must be re-read.
+    SIM_FILE_UPDATE = 0,                  // A file on SIM has been updated.
+    SIM_INIT = 1,                         // SIM initialized. All files should be re-read.
+    SIM_RESET = 2                         // SIM reset. SIM power required, SIM may be locked a
+                                          // nd all files must be re-read.
 };
 
 enum SrvccState :int32_t {
@@ -938,15 +938,15 @@
 };
 
 enum PhoneRestrictedState : int32_t {
-    NONE = 0x00,                           // No restriction at all including voice/SMS/USSD/SS/AV64
-                                           // and packet data
-    CS_EMERGENCY = 0x01,                   // Block emergency call due to restriction. But allow all
-                                           // normal voice/SMS/USSD/SS/AV64.
-    CS_NORMAL = 0x02,                      // Block all normal voice/SMS/USSD/SS/AV64 due to
-                                           // restriction. Only Emergency call allowed.
-    CS_ALL = 0x04,                         // Block all voice/SMS/USSD/SS/AV64 including emergency
-                                           // call due to restriction.
-    PS_ALL = 0x10                          // Block packet data access due to restriction.
+    NONE = 0x00,                          // No restriction at all including voice/SMS/USSD/SS/AV64
+                                          // and packet data
+    CS_EMERGENCY = 0x01,                  // Block emergency call due to restriction. But allow all
+                                          // normal voice/SMS/USSD/SS/AV64.
+    CS_NORMAL = 0x02,                     // Block all normal voice/SMS/USSD/SS/AV64 due to
+                                          // restriction. Only Emergency call allowed.
+    CS_ALL = 0x04,                        // Block all voice/SMS/USSD/SS/AV64 including emergency
+                                          // call due to restriction.
+    PS_ALL = 0x10                         // Block packet data access due to restriction.
 };
 
 enum CdmaCallWaitingNumberPresentation : int32_t {
@@ -1199,7 +1199,7 @@
 };
 
 struct TdScdmaSignalStrength {
-    uint32_t rscp;                        // The Received Signal Code Power in dBm multipled by -1.
+    uint32_t rscp;                        // The Received Signal Code Power in dBm multiplied by -1.
                                           // Range : 25 to 120
                                           // INT_MAX: 0x7FFFFFFF denotes invalid value.
                                           // Reference: 3GPP TS 25.123, section 9.1.1.1
@@ -1228,7 +1228,7 @@
     int32_t suggestedRetryTime;           // If status != 0, this fields indicates the suggested
                                           // retry back-off timer value RIL wants to override the
                                           // one pre-configured in FW.
-                                          // The unit is miliseconds.
+                                          // The unit is milliseconds.
                                           // The value < 0 means no value is suggested.
                                           // The value 0 means retry must be done ASAP.
                                           // The value of INT_MAX(0x7fffffff) means no retry.
@@ -1266,7 +1266,7 @@
     int32_t command;                      // one of the commands listed for TS 27.007 +CRSM
     int32_t fileId;                       // EF id
     string path;                          // "pathid" from TS 27.007 +CRSM command.
-                                          // Path is in hex asciii format eg "7f205f70"
+                                          // Path is in hex ascii format eg "7f205f70"
                                           // Path must always be provided.
     int32_t p1;                           // Values of p1, p2 and p3 defined as per 3GPP TS 51.011
     int32_t p2;
@@ -1385,7 +1385,7 @@
     int32_t reasonDataDenied;             // if registration state is 3 (Registration
                                           // denied) this is an enumerated reason why
                                           // registration was denied. See 3GPP TS 24.008,
-                                          // Annex G.6 "Additonal cause codes for GMM".
+                                          // Annex G.6 "Additional cause codes for GMM".
                                           // 7 == GPRS services not allowed
                                           // 8 == GPRS services and non-GPRS services not allowed
                                           // 9 == MS identity cannot be derived by the network
@@ -1415,7 +1415,7 @@
     int32_t serviceClass;                 // From 27.007 +CCFC/+CLCK "class"
                                           // See table for Android mapping from
                                           // MMI service code
-                                          // 0 means user doesnt input class
+                                          // 0 means user doesn't input class
     int32_t toa;                          // "type" from TS 27.007 7.11
     string number;                        // "number" from TS 27.007 7.11.
     int32_t timeSeconds;
@@ -1439,27 +1439,27 @@
 };
 
 struct CdmaSmsAddress {
-    CdmaSmsDigitMode digitMode;          // CdmaSmsDigitMode is of two types : 4 bit and 8 bit.
-                                         // For 4-bit type, only "digits" field defined below in
-                                         // this struct is used.
-    CdmaSmsNumberMode numberMode;        // Used only when digitMode is 8-bit
-    CdmaSmsNumberType numberType;        // Used only when digitMode is 8-bit.
-                                         // To specify an international address, use the following:
-                                         // digitMode = CdmaSmsDigitMode:EIGHT_BIT:
-                                         // numberMode = CdmaSmsNumberMode:NOT_DATA_NETWORK
-                                         // numberType = CdmaSmsNumberType:INTERNATIONAL_OR_DATA_IP
-                                         // numberPlan = CdmaSmsNumberPlan:TELEPHONY
-                                         // numberOfDigits = number of digits
-                                         // digits = ASCII digits, e.g. '1', '2', '3', '4', and '5'
-    CdmaSmsNumberPlan numberPlan;        // Used only when digitMode is 8-bit
-    vec<uint8_t> digits;                 // Each byte in this array represents a 4 bit or 8-bit digit
-                                         // of address data
+    CdmaSmsDigitMode digitMode;           // CdmaSmsDigitMode is of two types : 4 bit and 8 bit.
+                                          // For 4-bit type, only "digits" field defined below in
+                                          // this struct is used.
+    CdmaSmsNumberMode numberMode;         // Used only when digitMode is 8-bit
+    CdmaSmsNumberType numberType;         // Used only when digitMode is 8-bit.
+                                          // To specify an international address, use the following:
+                                          // digitMode = CdmaSmsDigitMode:EIGHT_BIT:
+                                          // numberMode = CdmaSmsNumberMode:NOT_DATA_NETWORK
+                                          // numberType = CdmaSmsNumberType:INTERNATIONAL_OR_DATA_IP
+                                          // numberPlan = CdmaSmsNumberPlan:TELEPHONY
+                                          // numberOfDigits = number of digits
+                                          // digits = ASCII digits, e.g. '1', '2', '3', '4', and '5'
+    CdmaSmsNumberPlan numberPlan;         // Used only when digitMode is 8-bit
+    vec<uint8_t> digits;                  // Each byte in this array represents a 4 bit or 8-bit
+                                          // digit of address data
 };
 
 struct CdmaSmsSubaddress {
     CdmaSmsSubaddressType subaddressType;
-    bool odd;                            // true means the last byte's lower 4 bits must be ignored
-    vec<uint8_t> digits;                 // Each byte respresents an 8-bit digit of subaddress data
+    bool odd;                             // true means the last byte's lower 4 bits must be ignored
+    vec<uint8_t> digits;                  // Each byte represents an 8-bit digit of subaddress data
 };
 
 struct CdmaSmsMessage {
@@ -1468,29 +1468,29 @@
     int32_t serviceCategory;
     CdmaSmsAddress address;
     CdmaSmsSubaddress subAddress;
-    vec<uint8_t> bearerData;             // 3GPP2 C.S0015-B, v2.0,
+    vec<uint8_t> bearerData;              // 3GPP2 C.S0015-B, v2.0,
 };
 
 struct CdmaSmsAck {
     CdmaSmsErrorClass errorClass;
-    int32_t smsCauseCode;                // As defined in N.S00005, 6.5.2.125.
-                                         // Currently, only 35 (resource shortage) and
-                                         // 39 (other terminal problem) are reported.
+    int32_t smsCauseCode;                 // As defined in N.S00005, 6.5.2.125.
+                                          // Currently, only 35 (resource shortage) and
+                                          // 39 (other terminal problem) are reported.
 };
 
 struct CdmaBroadcastSmsConfigInfo {
-    int32_t serviceCategory;             // serviceCategory defines a Broadcast message identifier
-                                         // whose value is 0x0000 - 0xFFFF as defined in
-                                         // C.R1001G 9.3.1 and 9.3.2.
-    int32_t language;                    // language code of Broadcast Message
-                                         // whose value is 0x00 - 0x07 as defined in C.R1001G 9.2.
-    bool selected;                       // selected false means message types specified in
-                                         // serviceCategory are not accepted, while true means
-                                         // accepted.
+    int32_t serviceCategory;              // serviceCategory defines a Broadcast message identifier
+                                          // whose value is 0x0000 - 0xFFFF as defined in
+                                          // C.R1001G 9.3.1 and 9.3.2.
+    int32_t language;                     // language code of Broadcast Message
+                                          // whose value is 0x00 - 0x07 as defined in C.R1001G 9.2.
+    bool selected;                        // selected false means message types specified in
+                                          // serviceCategory are not accepted, while true means
+                                          // accepted.
 };
 
 struct CdmaSmsWriteArgs {
-    CdmaSmsWriteArgsStatus status;       // Status of message. See TS 27.005 3.1
+    CdmaSmsWriteArgsStatus status;        // Status of message. See TS 27.005 3.1
     CdmaSmsMessage message;
 };
 
@@ -1520,68 +1520,68 @@
 };
 
 struct CellIdentityGsm {
-    string mcc;                          // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                          // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
-                                         // unknown
-    int32_t lac;                         // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
-    int32_t cid;                         // 16-bit GSM Cell Identity described in
-                                         // TS 27.007, 0..65535, INT_MAX if unknown
-    int32_t arfcn;                       // 16-bit GSM Absolute RF channel number, INT_MAX if
-                                         // unknown
-    uint8_t bsic;                        // 6-bit Base Station Identity Code, 0xFF if unknown
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+                                          // unknown
+    int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+    int32_t cid;                          // 16-bit GSM Cell Identity described in
+                                          // TS 27.007, 0..65535, INT_MAX if unknown
+    int32_t arfcn;                        // 16-bit GSM Absolute RF channel number, INT_MAX if
+                                          // unknown
+    uint8_t bsic;                         // 6-bit Base Station Identity Code, 0xFF if unknown
 };
 
 struct CellIdentityWcdma {
-    string mcc;                          // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                          // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX
-                                         // if unknown
-    int32_t lac;                         // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
-    int32_t cid;                         // 28-bit UMTS Cell Identity described in
-                                         // TS 25.331, 0..268435455, INT_MAX if unknown
-    int32_t psc;                         // 9-bit UMTS Primary Scrambling Code described in
-                                         // TS 25.331, 0..511, INT_MAX if unknown
-    int32_t uarfcn;                      // 16-bit UMTS Absolute RF Channel Number, INT_MAX if
-                                         // unknown
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX
+                                          // if unknown
+    int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
+    int32_t cid;                          // 28-bit UMTS Cell Identity described in
+                                          // TS 25.331, 0..268435455, INT_MAX if unknown
+    int32_t psc;                          // 9-bit UMTS Primary Scrambling Code described in
+                                          // TS 25.331, 0..511, INT_MAX if unknown
+    int32_t uarfcn;                       // 16-bit UMTS Absolute RF Channel Number, INT_MAX if
+                                          // unknown
 };
 
 struct CellIdentityCdma {
-    int32_t networkId;                   // Network Id 0..65535, INT_MAX if unknown
-    int32_t systemId;                    // CDMA System Id 0..32767, INT_MAX if unknown
-    int32_t basestationId;               // Base Station Id 0..65535, INT_MAX if unknown
-    int32_t longitude;                   // Longitude is a decimal number as specified in
-                                         // 3GPP2 C.S0005-A v6.0. It is represented in units of
-                                         // 0.25 seconds and ranges from -2592000 to 2592000,
-                                         // both values inclusive (corresponding to a range of -180
-                                         // to +180 degrees). INT_MAX if unknown
-    int32_t latitude;                    // Latitude is a decimal number as specified in
-                                         // 3GPP2 C.S0005-A v6.0. It is represented in units of
-                                         // 0.25 seconds and ranges from -1296000 to 1296000,
-                                         // both values inclusive (corresponding to a range of -90
-                                         // to +90 degrees). INT_MAX if unknown
+    int32_t networkId;                    // Network Id 0..65535, INT_MAX if unknown
+    int32_t systemId;                     // CDMA System Id 0..32767, INT_MAX if unknown
+    int32_t baseStationId;                // Base Station Id 0..65535, INT_MAX if unknown
+    int32_t longitude;                    // Longitude is a decimal number as specified in
+                                          // 3GPP2 C.S0005-A v6.0. It is represented in units of
+                                          // 0.25 seconds and ranges from -2592000 to 2592000,
+                                          // both values inclusive (corresponding to a range of -180
+                                          // to +180 degrees). INT_MAX if unknown
+    int32_t latitude;                     // Latitude is a decimal number as specified in
+                                          // 3GPP2 C.S0005-A v6.0. It is represented in units of
+                                          // 0.25 seconds and ranges from -1296000 to 1296000,
+                                          // both values inclusive (corresponding to a range of -90
+                                          // to +90 degrees). INT_MAX if unknown
 };
 
 struct CellIdentityLte {
-    string mcc;                          // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                          // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
-                                         // unknown
-    int32_t ci;                          // 28-bit Cell Identity described in TS TS 27.007, INT_MAX
-                                         // if unknown
-    int32_t pci;                         // physical cell id 0..503, INT_MAX if unknown
-    int32_t tac;                         // 16-bit tracking area code, INT_MAX if unknown
-    int32_t earfcn;                      // 18-bit LTE Absolute RC Channel Number, INT_MAX if
-                                         // unknown
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+                                          // unknown
+    int32_t ci;                           // 28-bit Cell Identity described in TS TS 27.007, INT_MAX
+                                          // if unknown
+    int32_t pci;                          // physical cell id 0..503, INT_MAX if unknown
+    int32_t tac;                          // 16-bit tracking area code, INT_MAX if unknown
+    int32_t earfcn;                       // 18-bit LTE Absolute RC Channel Number, INT_MAX if
+                                          // unknown
 };
 
 struct CellIdentityTdscdma {
-    string mcc;                          // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                          // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
-                                         // unknown
-    int32_t lac;                         // 16-bit Location Area Code, 0..65535, INT_MAX if
-                                         // unknown
-    int32_t cid;                         // 28-bit UMTS Cell Identity described in
-                                         // TS 25.331, 0..268435455, INT_MAX if unknown
-    int32_t cpid;                        // 8-bit Cell Parameters ID described in
-                                         // TS 25.331, 0..127, INT_MAX if unknown
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+                                          // unknown
+    int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if
+                                          // unknown
+    int32_t cid;                          // 28-bit UMTS Cell Identity described in
+                                          // TS 25.331, 0..268435455, INT_MAX if unknown
+    int32_t cpid;                         // 8-bit Cell Parameters ID described in
+                                          // TS 25.331, 0..127, INT_MAX if unknown
 };
 
 struct CellInfoGsm {
@@ -1611,56 +1611,57 @@
 };
 
 struct CellInfo {
-    CellInfoType cellInfoType;           // cell type for selecting from union CellInfo
-    bool registered;                     // true if this cell is registered false if not registered
-    TimeStampType timeStampType;         // type of time stamp represented by timeStamp
-    uint64_t timeStamp;                  // Time in nanos as returned by ril_nano_time
+    CellInfoType cellInfoType;            // cell type for selecting from union CellInfo
+    bool registered;                      // true if this cell is registered false if not registered
+    TimeStampType timeStampType;          // type of time stamp represented by timeStamp
+    uint64_t timeStamp;                   // Time in nanos as returned by ril_nano_time
     // Only one of the below vectors must be of size 1 based on the CellInfoType and others must be
     // of size 0
-    vec<CellInfoGsm> gsm;                // Valid only if type = gsm and size = 1 else must be empty
-    vec<CellInfoCdma> cdma;              // Valid only if type = cdma and size = 1 else must be
-                                         // empty
-    vec<CellInfoLte> lte;                // Valid only if type = lte and size = 1 else must be
-                                         // empty
-    vec<CellInfoWcdma> wcdma;            // Valid only if type = wcdma and size = 1 else must be
-                                         // empty
-    vec<CellInfoTdscdma> tdscdma;        // Valid only if type = tdscdma and size = 1 else must be
-                                         // empty
+    vec<CellInfoGsm> gsm;                 // Valid only if type = gsm and size = 1 else must be
+                                          // empty
+    vec<CellInfoCdma> cdma;               // Valid only if type = cdma and size = 1 else must be
+                                          // empty
+    vec<CellInfoLte> lte;                 // Valid only if type = lte and size = 1 else must be
+                                          // empty
+    vec<CellInfoWcdma> wcdma;             // Valid only if type = wcdma and size = 1 else must be
+                                          // empty
+    vec<CellInfoTdscdma> tdscdma;         // Valid only if type = tdscdma and size = 1 else must be
+                                          // empty
 };
 
 struct GsmSmsMessage {
-    string smscPdu;                      // SMSC address in GSM BCD format prefixed by a length
-                                         // byte (as expected by TS 27.005) or empty string for
-                                         // default SMSC
-    string pdu;                          // SMS in PDU format as an ASCII hex string less the
-                                         // SMSC address. TP-Layer-Length is be "strlen(pdu)/2
+    string smscPdu;                       // SMSC address in GSM BCD format prefixed by a length
+                                          // byte (as expected by TS 27.005) or empty string for
+                                          // default SMSC
+    string pdu;                           // SMS in PDU format as an ASCII hex string less the
+                                          // SMSC address. TP-Layer-Length is be "strlen(pdu)/2
 };
 
 struct ImsSmsMessage {
     RadioTechnologyFamily tech;
-    bool retry;                          // false == not retry, true == retry */
-    int32_t messageRef;                  // Valid field if retry is set to true.
-                                         // Contains messageRef from SendSmsResult stuct
-                                         // corresponding to failed MO SMS.
+    bool retry;                           // false == not retry, true == retry */
+    int32_t messageRef;                   // Valid field if retry is set to true.
+                                          // Contains messageRef from SendSmsResult struct
+                                          // corresponding to failed MO SMS.
     // Only one of the below vectors must be of size 1 based on the RadioTechnologyFamily and others
     // must be of size 0
-    vec<CdmaSmsMessage> cdmaMessage;     // Valid field if tech is 3GPP2 and size = 1 else must be
-                                         // empty
-    vec<GsmSmsMessage> gsmMessage;       // Valid field if tech is 3GPP and size = 1 else must be
-                                         // empty
+    vec<CdmaSmsMessage> cdmaMessage;      // Valid field if tech is 3GPP2 and size = 1 else must be
+                                          // empty
+    vec<GsmSmsMessage> gsmMessage;        // Valid field if tech is 3GPP and size = 1 else must be
+                                          // empty
 };
 
 struct SimApdu {
-    int32_t sessionId;                   // "sessionid" from TS 27.007 +CGLA command. Must be
-                                         // ignored for +CSIM command.
+    int32_t sessionId;                    // "sessionid" from TS 27.007 +CGLA command. Must be
+                                          // ignored for +CSIM command.
     // Following fields are used to derive the APDU ("command" and "length"
     // values in TS 27.007 +CSIM and +CGLA commands).
     int32_t cla;
     int32_t instruction;
     int32_t p1;
     int32_t p2;
-    int32_t p3;                          // A negative P3 implies a 4 byte APDU.
-    string data;                         // In hex string format ([a-fA-F0-9]*).
+    int32_t p3;                           // A negative P3 implies a 4 byte APDU.
+    string data;                          // In hex string format ([a-fA-F0-9]*).
 };
 
 struct NvWriteItem {
@@ -1670,160 +1671,159 @@
 
 struct SelectUiccSub {
     int32_t slot;
-    int32_t appIndex;                   // array subscriptor from
-                                        // applications[RadioConst:CARD_MAX_APPS] in
-                                        // getIccCardStatus()
+    int32_t appIndex;                     // array subscriptor from
+                                          // applications[RadioConst:CARD_MAX_APPS] in
+                                          // getIccCardStatus()
     SubscriptionType subType;
     UiccSubActStatus actStatus;
 };
 
 struct HardwareConfigModem {
     int32_t rilModel;
-    uint32_t rat;                       // bitset - ref. RadioTechnology.
+    uint32_t rat;                         // bitset - ref. RadioTechnology.
     int32_t maxVoice;
     int32_t maxData;
     int32_t maxStandby;
 };
 
 struct HardwareConfigSim {
-    string modemUuid;                   // RadioConst:MAX_UUID_LENGTH is max length of the
-                                        // string
+    string modemUuid;                     // RadioConst:MAX_UUID_LENGTH is max length of the string
 };
 
 struct HardwareConfig {
     HardwareConfigType type;
-    string uuid;                         // RadioConst:MAX_UUID_LENGTH is max length of the
-                                         // string
+    string uuid;                          // RadioConst:MAX_UUID_LENGTH is max length of the string
     HardwareConfigState state;
+
     // Only one of the below vectors must have size = 1 based on the HardwareConfigType and other
     // must have size = 0.
-    vec<HardwareConfigModem> modem;      // Valid only if type is Modem and size = 1 else must be
-                                         // empty
-    vec<HardwareConfigSim> sim;          // Valid only if type is SIM or else emptyand size = 1
-                                         // else must be empty
+    vec<HardwareConfigModem> modem;       // Valid only if type is Modem and size = 1 else must be
+                                          // empty
+    vec<HardwareConfigSim> sim;           // Valid only if type is SIM or else empty and size = 1
+                                          // else must be empty
 };
 
 struct DataProfileInfo {
-    int32_t profileId;                   // id of the data profile
-    string apn;                          // The APN to connect to
-    string protocol;                     // One of the PDP_type values in TS 27.007 section 10.1.1.
-                                         // For example, "IP", "IPV6", "IPV4V6", or "PPP".
+    int32_t profileId;                    // id of the data profile
+    string apn;                           // The APN to connect to
+    string protocol;                      // One of the PDP_type values in TS 27.007 section 10.1.1.
+                                          // For example, "IP", "IPV6", "IPV4V6", or "PPP".
     ApnAuthType authType;
-    string user;                         // The username for APN, or empty string
-    string password;                     // The password for APN, or empty string
+    string user;                          // The username for APN, or empty string
+    string password;                      // The password for APN, or empty string
     DataProfileInfoType type;
-    int32_t maxConnsTime;                // The period in seconds to limit the maximum connections
-    int32_t maxConns;                    // The maximum connections during maxConnsTime
-    int32_t waitTime;                    // The required wait time in seconds after a successful UE
-                                         // initiated disconnect of a given PDN connection before
-                                         // the device can send a new PDN connection request for
-                                         // that given PDN
-    bool enabled;                        // True to enable the profile, false to disable
+    int32_t maxConnsTime;                 // The period in seconds to limit the maximum connections
+    int32_t maxConns;                     // The maximum connections during maxConnsTime
+    int32_t waitTime;                     // The required wait time in seconds after a successful UE
+                                          // initiated disconnect of a given PDN connection before
+                                          // the device can send a new PDN connection request for
+                                          // that given PDN
+    bool enabled;                         // True to enable the profile, false to disable
 };
 
 struct RadioCapability {
-    int32_t session;                     // Unique session value defined by framework returned in
-                                         // all "responses/unsol"
+    int32_t session;                      // Unique session value defined by framework returned in
+                                          // all "responses/unsol"
     RadioCapabilityPhase phase;
-    RadioAccessFamily raf;
-    string logicalModemUuid;             // A UUID typically "com.xxxx.lmX where X is the logical
-                                         // modem. RadioConst:MAX_UUID_LENGTH is the max
-                                         // length
+    bitfield<RadioAccessFamily> raf;      // 32-bit bitmap of RadioAccessFamily
+    string logicalModemUuid;              // A UUID typically "com.xxxx.lmX where X is the logical
+                                          // modem. RadioConst:MAX_UUID_LENGTH is the max
+                                          // length
     RadioCapabilityStatus status;
 };
 
 struct LceStatusInfo {
     LceStatus lceStatus;
-    uint8_t actualIntervalMs;            // actual LCE reporting interval,
-                                         // meaningful only if LceStatus = ACTIVE.
+    uint8_t actualIntervalMs;             // actual LCE reporting interval,
+                                          // meaningful only if LceStatus = ACTIVE.
 };
 
 struct LceDataInfo {
-    uint32_t lastHopCapacityKbps;          // last-hop cellular capacity: kilobits/second.
-    uint8_t confidenceLevel;               // capacity estimate confidence: 0-100
-    bool lceSuspended;                     // LCE report going to be suspended? (e.g., radio
-                                           // moves to inactive state or network type change)
-                                           // true = suspended;
-                                           // false = not suspended.
+    uint32_t lastHopCapacityKbps;         // last-hop cellular capacity: kilobits/second.
+    uint8_t confidenceLevel;              // capacity estimate confidence: 0-100
+    bool lceSuspended;                    // LCE report going to be suspended? (e.g., radio
+                                          // moves to inactive state or network type change)
+                                          // true = suspended;
+                                          // false = not suspended.
 };
 
 struct ActivityStatsInfo {
-    uint32_t sleepModeTimeMs;              // total time (in ms) when modem is in a low power or
-                                           // sleep state
-    uint32_t idleModeTimeMs;               // total time (in ms) when modem is awake but neither
-                                           // the transmitter nor receiver are active/awake
+    uint32_t sleepModeTimeMs;             // total time (in ms) when modem is in a low power or
+                                          // sleep state
+    uint32_t idleModeTimeMs;              // total time (in ms) when modem is awake but neither
+                                          // the transmitter nor receiver are active/awake
     uint32_t[RadioConst:NUM_TX_POWER_LEVELS] txmModetimeMs;
-                                           // Each index represent total time (in ms) during which
-                                           // the transmitter is active/awake for a particular
-                                           // power range as shown below.
-                                           // index 0 = tx_power < 0dBm
-                                           // index 1 = 0dBm < tx_power < 5dBm
-                                           // index 2 = 5dBm < tx_power < 15dBm
-                                           // index 3 = 15dBm < tx_power < 20dBm
-                                           // index 4 = tx_power > 20dBm
-    uint32_t rxModeTimeMs;                 // total time (in ms) for which receiver is
-                                           // active/awake and the transmitter is inactive
+                                          // Each index represent total time (in ms) during which
+                                          // the transmitter is active/awake for a particular
+                                          // power range as shown below.
+                                          // index 0 = tx_power < 0dBm
+                                          // index 1 = 0dBm < tx_power < 5dBm
+                                          // index 2 = 5dBm < tx_power < 15dBm
+                                          // index 3 = 15dBm < tx_power < 20dBm
+                                          // index 4 = tx_power > 20dBm
+    uint32_t rxModeTimeMs;                // total time (in ms) for which receiver is
+                                          // active/awake and the transmitter is inactive
 };
 
 struct Carrier {
     string mcc;
     string mnc;
-    CarrierMatchType matchType;            // Specify match type for the carrier.
-                                           // If it’s ALL, matchData is empty string;
-                                           // otherwise, matchData is the value for the match type.
+    CarrierMatchType matchType;           // Specify match type for the carrier.
+                                          // If it’s ALL, matchData is empty string;
+                                          // otherwise, matchData is the value for the match type.
     string matchData;
 };
 
 struct CarrierRestrictions {
-    vec<Carrier> allowedCarriers;          // whitelist for allowed carriers
-    vec<Carrier> excludedCarriers;         // blacklist for explicitly excluded carriers
-                                           // which match allowed_carriers. Eg. allowedCarriers
-                                           // match mcc/mnc, excludedCarriers has same mcc/mnc and
-                                           // gid1 is ABCD. It means except the carrier whose gid1
-                                           // is ABCD, all carriers with the same mcc/mnc are
-                                           // allowed.
+    vec<Carrier> allowedCarriers;         // whitelist for allowed carriers
+    vec<Carrier> excludedCarriers;        // blacklist for explicitly excluded carriers
+                                          // which match allowed_carriers. Eg. allowedCarriers
+                                          // match mcc/mnc, excludedCarriers has same mcc/mnc and
+                                          // gid1 is ABCD. It means except the carrier whose gid1
+                                          // is ABCD, all carriers with the same mcc/mnc are
+                                          // allowed.
 };
 
 struct SuppSvcNotification {
-    bool isMT;                             // notification type
-                                           // false = MO intermediate result code
-                                           // true = MT unsolicited result code
-    int32_t code;                          // result code. See 27.007 7.17.
-    int32_t index;                         // CUG index. See 27.007 7.17.
-    int32_t type;                          // "type" from 27.007 7.17 (MT only).
-    string number;                         // "number" from 27.007 7.17
-                                           // (MT only, may be empty string).
+    bool isMT;                            // notification type
+                                          // false = MO intermediate result code
+                                          // true = MT unsolicited result code
+    int32_t code;                         // result code. See 27.007 7.17.
+    int32_t index;                        // CUG index. See 27.007 7.17.
+    int32_t type;                         // "type" from 27.007 7.17 (MT only).
+    string number;                        // "number" from 27.007 7.17
+                                          // (MT only, may be empty string).
 };
 
 struct SimRefreshResult {
     SimRefreshType type;
-    int32_t efId;                          // is the EFID of the updated file if the result is
-                                           // SIM_FILE_UPDATE or 0 for any other result.
-    string aid;                            // is AID(application ID) of the card application
-                                           // See ETSI 102.221 8.1 and 101.220 4
-                                           // For SIM_FILE_UPDATE result it must be set to AID of
-                                           // application in which updated EF resides or it must be
-                                           // empty string if EF is outside of an application.
-                                           // For SIM_INIT result this field is set to AID of
-                                           // application that caused REFRESH
-                                           // For SIM_RESET result it is empty string.
+    int32_t efId;                         // is the EFID of the updated file if the result is
+                                          // SIM_FILE_UPDATE or 0 for any other result.
+    string aid;                           // is AID(application ID) of the card application
+                                          // See ETSI 102.221 8.1 and 101.220 4
+                                          // For SIM_FILE_UPDATE result it must be set to AID of
+                                          // application in which updated EF resides or it must be
+                                          // empty string if EF is outside of an application.
+                                          // For SIM_INIT result this field is set to AID of
+                                          // application that caused REFRESH
+                                          // For SIM_RESET result it is empty string.
 };
 
 /* CDMA Signal Information Record as defined in C.S0005 section 3.7.5.5 */
 struct CdmaSignalInfoRecord {
-    bool isPresent;                        // true if signal information record is present
-    int8_t signalType;                     // as defined 3.7.5.5-1
-    int8_t alertPitch;                     // as defined 3.7.5.5-2
-    int8_t signal;                         // as defined 3.7.5.5-3, 3.7.5.5-4 or 3.7.5.5-5
+    bool isPresent;                       // true if signal information record is present
+    int8_t signalType;                    // as defined 3.7.5.5-1
+    int8_t alertPitch;                    // as defined 3.7.5.5-2
+    int8_t signal;                        // as defined 3.7.5.5-3, 3.7.5.5-4 or 3.7.5.5-5
 };
 
 struct CdmaCallWaiting {
-    string number;                         // Remote party number
+    string number;                        // Remote party number
     CdmaCallWaitingNumberPresentation numberPresentation;
-    string name;                           // Remote party name
+    string name;                          // Remote party name
     CdmaSignalInfoRecord signalInfoRecord;
     // Number type/Number plan required to support International Call Waiting
-    CdmaCallWaitingNumberType numbertype;
+    CdmaCallWaitingNumberType numberType;
     CdmaCallWaitingNumberPlan numberPlan;
 };
 
@@ -1837,7 +1837,7 @@
  * The display_tag, display_len and chari fields are all 1 byte.
  */
 struct CdmaDisplayInfoRecord {
-    string alphaBuf;                       // Max length = RadioConst:CDMA_ALPHA_INFO_BUFFER_LENGTH
+    string alphaBuf;                      // Max length = RadioConst:CDMA_ALPHA_INFO_BUFFER_LENGTH
 };
 
 /*
@@ -1846,7 +1846,7 @@
  * Connected Number Info Rec as defined in C.S0005 section 3.7.5.4
  */
 struct CdmaNumberInfoRecord {
-    string number;                         // Max length = RADIP_CDMA_NUMBER_INFO_BUFFER_LENGTH
+    string number;                        // Max length = RADIP_CDMA_NUMBER_INFO_BUFFER_LENGTH
     uint8_t numberType;
     uint8_t numberPlan;
     uint8_t pi;
@@ -1881,56 +1881,56 @@
     CdmaInfoRecName name;
     // Only one of the below vectors must have size = 1 based on the
     // CdmaInfoRecName. All other vectors must have size 0.
-    vec<CdmaDisplayInfoRecord> display;  // Display and Extended Display Info Rec
-    vec<CdmaNumberInfoRecord> number;    // Called Party Number, Calling Party Number, Connected
-                                         // number Info Rec
-    vec<CdmaSignalInfoRecord> signal;    // Signal Info Rec
+    vec<CdmaDisplayInfoRecord> display;   // Display and Extended Display Info Rec
+    vec<CdmaNumberInfoRecord> number;     // Called Party Number, Calling Party Number, Connected
+                                          // number Info Rec
+    vec<CdmaSignalInfoRecord> signal;     // Signal Info Rec
     vec<CdmaRedirectingNumberInfoRecord> redir; // Redirecting Number Info Rec
     vec<CdmaLineControlInfoRecord> lineCtrl;    // Line Control Info Rec
-    vec<CdmaT53ClirInfoRecord> clir;     // T53 CLIR Info Rec
+    vec<CdmaT53ClirInfoRecord> clir;      // T53 CLIR Info Rec
     vec<CdmaT53AudioControlInfoRecord> audioCtrl; // T53 Audio Control Info Rec
 };
 
 struct CdmaInformationRecords {
-    vec<CdmaInformationRecord> infoRec;  // Max length = RadioConst:CDMA_MAX_NUMBER_OF_INFO_RECS
+    vec<CdmaInformationRecord> infoRec;   // Max length = RadioConst:CDMA_MAX_NUMBER_OF_INFO_RECS
 };
 
 struct CfData {
-    vec<CallForwardInfo> cfInfo;         // This is the response data
-                                         // for SS request to query call
-                                         // forward status. see getCallForwardStatus()
-                                         // Max size = RadioConst:NUM_SERVICE_CLASSES
+    vec<CallForwardInfo> cfInfo;          // This is the response data
+                                          // for SS request to query call
+                                          // forward status. see getCallForwardStatus()
+                                          // Max size = RadioConst:NUM_SERVICE_CLASSES
 };
 
 struct SsInfoData {
-    vec<int32_t> ssInfo;                 // This is the response data for all of the SS GET/SET
-                                         // Radio requests. E.g. IRadio.getClir() returns
-                                         // two ints, so first two values of ssInfo[] will be
-                                         // used for response if serviceType is SS_CLIR and
-                                         // requestType is SS_INTERROGATION
-                                         // Max size = RadioConst:SS_INFO_MAX
+    vec<int32_t> ssInfo;                  // This is the response data for all of the SS GET/SET
+                                          // Radio requests. E.g. IRadio.getClir() returns
+                                          // two ints, so first two values of ssInfo[] will be
+                                          // used for response if serviceType is SS_CLIR and
+                                          // requestType is SS_INTERROGATION
+                                          // Max size = RadioConst:SS_INFO_MAX
 };
 
 struct StkCcUnsolSsResult {
     SsServiceType serviceType;
     SsRequestType requestType;
     SsTeleserviceType teleserviceType;
-    SuppServiceClass serviceClass;
+    bitfield<SuppServiceClass> serviceClass;
     RadioError result;
     // Only one of the below vectors may contain values and other must be empty
-    vec<SsInfoData> ssInfo;              // Valid only for all SsserviceType except
-                                         // SsServiceType:CF_* else empty.
-    vec<CfData> cfData;                  // Valid for SsServiceType:CF_* else empty
+    vec<SsInfoData> ssInfo;               // Valid only for all SsServiceType except
+                                          // SsServiceType:CF_* else empty.
+    vec<CfData> cfData;                   // Valid for SsServiceType:CF_* else empty
 };
 
 struct PcoDataInfo {
-    int32_t cid;                         // Context ID, uniquely identifies this call
-    string bearerProto;                  // One of the PDP_type values in TS 27.007 section 10.1.1.
-                                         // For example, "IP", "IPV6", "IPV4V6"
-    int32_t pcoId;                       // The protocol ID for this box. Note that only IDs from
-                                         // FF00H - FFFFH are accepted. If more than one is
-                                         // included from the network, multiple calls must be made
-                                         // to send all of them.
-    vec<uint8_t> contents;               // Carrier-defined content. It is binary, opaque and
-                                         // loosely defined in LTE Layer 3 spec 24.008
+    int32_t cid;                          // Context ID, uniquely identifies this call
+    string bearerProto;                   // One of the PDP_type values in TS 27.007 section 10.1.1.
+                                          // For example, "IP", "IPV6", "IPV4V6"
+    int32_t pcoId;                        // The protocol ID for this box. Note that only IDs from
+                                          // FF00H - FFFFH are accepted. If more than one is
+                                          // included from the network, multiple calls must be made
+                                          // to send all of them.
+    vec<uint8_t> contents;                // Carrier-defined content. It is binary, opaque and
+                                          // loosely defined in LTE Layer 3 spec 24.008
 };
diff --git a/radio/1.0/vts/Android.mk b/radio/1.0/vts/Android.mk
new file mode 100644
index 0000000..4e1fb84
--- /dev/null
+++ b/radio/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/radio/hidl/Android.mk
\ No newline at end of file
diff --git a/radio/1.0/vts/Radio.vts b/radio/1.0/vts/Radio.vts
new file mode 100644
index 0000000..c3d998a
--- /dev/null
+++ b/radio/1.0/vts/Radio.vts
@@ -0,0 +1,1497 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IRadio"
+
+package: "android.hardware.radio"
+
+import: "android.hardware.radio@1.0::IRadioIndication"
+import: "android.hardware.radio@1.0::IRadioResponse"
+import: "android.hardware.radio@1.0::types"
+
+interface: {
+    api: {
+        name: "setResponseFunctions"
+        arg: {
+            type: TYPE_HIDL_INTERFACE
+            predefined_type: "IRadioResponse"
+            is_callback: false
+        }
+        arg: {
+            type: TYPE_HIDL_INTERFACE
+            predefined_type: "IRadioIndication"
+            is_callback: false
+        }
+    }
+
+    api: {
+        name: "getIccCardStatus"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "supplyIccPinForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "supplyIccPukForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "supplyIccPin2ForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "supplyIccPuk2ForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "changeIccPinForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "changeIccPin2ForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "supplyNetworkDepersonalization"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "getCurrentCalls"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "dial"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::Dial"
+        }
+    }
+
+    api: {
+        name: "getImsiForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "hangup"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "hangupWaitingOrBackground"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "hangupForegroundResumeBackground"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "switchWaitingOrHoldingAndActive"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "conference"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "rejectCall"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getLastCallFailCause"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getSignalStrength"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getVoiceRegistrationState"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getDataRegistrationState"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getOperator"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setRadioPower"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "sendDtmf"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "sendSms"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::GsmSmsMessage"
+        }
+    }
+
+    api: {
+        name: "sendSMSExpectMore"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::GsmSmsMessage"
+        }
+    }
+
+    api: {
+        name: "setupDataCall"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::ApnAuthType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "iccIOForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIo"
+        }
+    }
+
+    api: {
+        name: "sendUssd"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "cancelPendingUssd"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getClir"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setClir"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getCallForwardStatus"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CallForwardInfo"
+        }
+    }
+
+    api: {
+        name: "setCallForward"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CallForwardInfo"
+        }
+    }
+
+    api: {
+        name: "getCallWaiting"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setCallWaiting"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "acknowledgeLastIncomingGsmSms"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SmsAcknowledgeFailCause"
+        }
+    }
+
+    api: {
+        name: "acceptCall"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "deactivateDataCall"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getFacilityLockForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "setFacilityLockForApp"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "setBarringPassword"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "getNetworkSelectionMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setNetworkSelectionModeAutomatic"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setNetworkSelectionModeManual"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "getAvailableNetworks"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "startDtmf"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "stopDtmf"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getBasebandVersion"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "separateConnection"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setMute"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getMute"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getClip"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getDataCallList"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "sendOemRadioRequestRaw"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "sendOemRadioRequestStrings"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRING
+            }
+        }
+    }
+
+    api: {
+        name: "sendScreenState"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "setSuppServiceNotifications"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "writeSmsToSim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SmsWriteArgs"
+        }
+    }
+
+    api: {
+        name: "deleteSmsOnSim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setBandMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioBandMode"
+        }
+    }
+
+    api: {
+        name: "getAvailableBandModes"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "sendEnvelope"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "sendTerminalResponseToSim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "handleStkCallSetupRequestFromSim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "explicitCallTransfer"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setPreferredNetworkType"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::PreferredNetworkType"
+        }
+    }
+
+    api: {
+        name: "getPreferredNetworkType"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getNeighboringCids"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setLocationUpdates"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "setCdmaSubscriptionSource"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSubscriptionSource"
+        }
+    }
+
+    api: {
+        name: "setCdmaRoamingPreference"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaRoamingType"
+        }
+    }
+
+    api: {
+        name: "getCdmaRoamingPreference"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setTTYMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::TtyMode"
+        }
+    }
+
+    api: {
+        name: "getTTYMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setPreferredVoicePrivacy"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getPreferredVoicePrivacy"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "sendCDMAFeatureCode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "sendBurstDtmf"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "sendCdmaSms"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSmsMessage"
+        }
+    }
+
+    api: {
+        name: "acknowledgeLastIncomingCdmaSms"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSmsAck"
+        }
+    }
+
+    api: {
+        name: "getGsmBroadcastConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setGsmBroadcastConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::GsmBroadcastSmsConfigInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setGsmBroadcastActivation"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getCdmaBroadcastConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setCdmaBroadcastConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::CdmaBroadcastSmsConfigInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setCdmaBroadcastActivation"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getCDMASubscription"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "writeSmsToRuim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSmsWriteArgs"
+        }
+    }
+
+    api: {
+        name: "deleteSmsOnRuim"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getDeviceIdentity"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "exitEmergencyCallbackMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getSmscAddress"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setSmscAddress"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "reportSmsMemoryStatus"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "reportStkServiceIsRunning"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getCdmaSubscriptionSource"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "requestIsimAuthentication"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "acknowledgeIncomingGsmSmsWithPdu"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "sendEnvelopeWithStatus"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "getVoiceRadioTechnology"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getCellInfoList"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setCellInfoListRate"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setInitialAttachApn"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::ApnAuthType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "getImsRegistrationState"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "sendImsSms"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::ImsSmsMessage"
+        }
+    }
+
+    api: {
+        name: "iccTransmitApduBasicChannel"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SimApdu"
+        }
+    }
+
+    api: {
+        name: "iccOpenLogicalChannel"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "iccCloseLogicalChannel"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "iccTransmitApduLogicalChannel"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SimApdu"
+        }
+    }
+
+    api: {
+        name: "nvReadItem"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::NvItem"
+        }
+    }
+
+    api: {
+        name: "nvWriteItem"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::NvWriteItem"
+        }
+    }
+
+    api: {
+        name: "nvWriteCdmaPrl"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "nvResetConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::ResetNvType"
+        }
+    }
+
+    api: {
+        name: "setUiccSubscription"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SelectUiccSub"
+        }
+    }
+
+    api: {
+        name: "setDataAllowed"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getHardwareConfig"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "requestIccSimAuthentication"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "setDataProfile"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::DataProfileInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "requestShutdown"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getRadioCapability"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setRadioCapability"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioCapability"
+        }
+    }
+
+    api: {
+        name: "startLceService"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "stopLceService"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "pullLceData"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getModemActivityInfo"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setAllowedCarriers"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CarrierRestrictions"
+        }
+    }
+
+    api: {
+        name: "getAllowedCarriers"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "responseAcknowledgement"
+    }
+
+}
diff --git a/radio/1.0/vts/RadioIndication.vts b/radio/1.0/vts/RadioIndication.vts
new file mode 100644
index 0000000..fac73a9
--- /dev/null
+++ b/radio/1.0/vts/RadioIndication.vts
@@ -0,0 +1,545 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IRadioIndication"
+
+package: "android.hardware.radio"
+
+import: "android.hardware.radio@1.0::types"
+
+interface: {
+    api: {
+        name: "radioStateChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioState"
+        }
+    }
+
+    api: {
+        name: "callStateChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "voiceNetworkStateChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "newSms"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "newSmsStatusReport"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "newSmsOnSim"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "onUssd"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::UssdModeType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "nitzTimeReceived"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint64_t"
+        }
+    }
+
+    api: {
+        name: "currentSignalStrength"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SignalStrength"
+        }
+    }
+
+    api: {
+        name: "dataCallListChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::SetupDataCallResult"
+            }
+        }
+    }
+
+    api: {
+        name: "suppSvcNotify"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SuppSvcNotification"
+        }
+    }
+
+    api: {
+        name: "stkSessionEnd"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "stkProactiveCommand"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "stkEventNotify"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "stkCallSetup"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int64_t"
+        }
+    }
+
+    api: {
+        name: "simSmsStorageFull"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "simRefresh"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SimRefreshResult"
+        }
+    }
+
+    api: {
+        name: "callRing"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSignalInfoRecord"
+        }
+    }
+
+    api: {
+        name: "simStatusChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "cdmaNewSms"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSmsMessage"
+        }
+    }
+
+    api: {
+        name: "newBroadcastSms"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "cdmaRuimSmsStorageFull"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "restrictedStateChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::PhoneRestrictedState"
+        }
+    }
+
+    api: {
+        name: "enterEmergencyCallbackMode"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "cdmaCallWaiting"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaCallWaiting"
+        }
+    }
+
+    api: {
+        name: "cdmaOtaProvisionStatus"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaOtaProvisionStatus"
+        }
+    }
+
+    api: {
+        name: "cdmaInfoRec"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaInformationRecords"
+        }
+    }
+
+    api: {
+        name: "oemHookRaw"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "indicateRingbackTone"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "resendIncallMute"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "cdmaSubscriptionSourceChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSubscriptionSource"
+        }
+    }
+
+    api: {
+        name: "cdmaPrlChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "exitEmergencyCallbackMode"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "rilConnected"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "voiceRadioTechChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioTechnology"
+        }
+    }
+
+    api: {
+        name: "cellInfoList"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::CellInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "imsNetworkStateChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+    }
+
+    api: {
+        name: "subscriptionStatusChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "srvccStateNotify"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SrvccState"
+        }
+    }
+
+    api: {
+        name: "hardwareConfigChanged"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::HardwareConfig"
+            }
+        }
+    }
+
+    api: {
+        name: "radioCapabilityIndication"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioCapability"
+        }
+    }
+
+    api: {
+        name: "onSupplementaryServiceIndication"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::StkCcUnsolSsResult"
+        }
+    }
+
+    api: {
+        name: "stkCallControlAlphaNotify"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "lceData"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::LceDataInfo"
+        }
+    }
+
+    api: {
+        name: "pcoData"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::PcoDataInfo"
+        }
+    }
+
+    api: {
+        name: "modemReset"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioIndicationType"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+}
diff --git a/radio/1.0/vts/RadioResponse.vts b/radio/1.0/vts/RadioResponse.vts
new file mode 100644
index 0000000..2884d30
--- /dev/null
+++ b/radio/1.0/vts/RadioResponse.vts
@@ -0,0 +1,1382 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IRadioResponse"
+
+package: "android.hardware.radio"
+
+import: "android.hardware.radio@1.0::types"
+
+interface: {
+    api: {
+        name: "getIccCardStatusResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CardStatus"
+        }
+    }
+
+    api: {
+        name: "supplyIccPinForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "supplyIccPukForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "supplyIccPin2ForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "supplyIccPuk2ForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "changeIccPinForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "changeIccPin2ForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "supplyNetworkDepersonalizationResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getCurrentCallsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::Call"
+            }
+        }
+    }
+
+    api: {
+        name: "dialResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getIMSIForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "hangupConnectionResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "hangupWaitingOrBackgroundResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "hangupForegroundResumeBackgroundResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "switchWaitingOrHoldingAndActiveResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "conferenceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "rejectCallResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getLastCallFailCauseResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::LastCallFailCauseInfo"
+        }
+    }
+
+    api: {
+        name: "getSignalStrengthResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SignalStrength"
+        }
+    }
+
+    api: {
+        name: "getVoiceRegistrationStateResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::VoiceRegStateResult"
+        }
+    }
+
+    api: {
+        name: "getDataRegistrationStateResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::DataRegStateResult"
+        }
+    }
+
+    api: {
+        name: "getOperatorResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "setRadioPowerResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "sendDtmfResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "sendSmsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SendSmsResult"
+        }
+    }
+
+    api: {
+        name: "sendSMSExpectMoreResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SendSmsResult"
+        }
+    }
+
+    api: {
+        name: "setupDataCallResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SetupDataCallResult"
+        }
+    }
+
+    api: {
+        name: "iccIOForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIoResult"
+        }
+    }
+
+    api: {
+        name: "sendUssdResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "cancelPendingUssdResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getClirResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setClirResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCallForwardStatusResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::CallForwardInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setCallForwardResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCallWaitingResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setCallWaitingResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "acknowledgeLastIncomingGsmSmsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "acceptCallResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "deactivateDataCallResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getFacilityLockForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setFacilityLockForAppResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setBarringPasswordResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getNetworkSelectionModeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "setNetworkSelectionModeAutomaticResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setNetworkSelectionModeManualResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getAvailableNetworksResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::OperatorInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "startDtmfResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "stopDtmfResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getBasebandVersionResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "separateConnectionResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setMuteResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getMuteResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "getClipResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::ClipStatus"
+        }
+    }
+
+    api: {
+        name: "getDataCallListResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::SetupDataCallResult"
+            }
+        }
+    }
+
+    api: {
+        name: "sendOemRilRequestRawResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "sendOemRilRequestStringsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRING
+            }
+        }
+    }
+
+    api: {
+        name: "sendScreenStateResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setSuppServiceNotificationsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "writeSmsToSimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "deleteSmsOnSimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setBandModeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getAvailableBandModesResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_ENUM
+                predefined_type: "::android::hardware::radio::V1_0::RadioBandMode"
+            }
+        }
+    }
+
+    api: {
+        name: "sendEnvelopeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "sendTerminalResponseToSimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "handleStkCallSetupRequestFromSimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "explicitCallTransferResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setPreferredNetworkTypeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getPreferredNetworkTypeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::PreferredNetworkType"
+        }
+    }
+
+    api: {
+        name: "getNeighboringCidsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::NeighboringCell"
+            }
+        }
+    }
+
+    api: {
+        name: "setLocationUpdatesResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setCdmaSubscriptionSourceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setCdmaRoamingPreferenceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCdmaRoamingPreferenceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaRoamingType"
+        }
+    }
+
+    api: {
+        name: "setTTYModeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getTTYModeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::TtyMode"
+        }
+    }
+
+    api: {
+        name: "setPreferredVoicePrivacyResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getPreferredVoicePrivacyResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "sendCDMAFeatureCodeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "sendBurstDtmfResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "sendCdmaSmsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SendSmsResult"
+        }
+    }
+
+    api: {
+        name: "acknowledgeLastIncomingCdmaSmsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getGsmBroadcastConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::GsmBroadcastSmsConfigInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setGsmBroadcastConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setGsmBroadcastActivationResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCdmaBroadcastConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::CdmaBroadcastSmsConfigInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setCdmaBroadcastConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setCdmaBroadcastActivationResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCDMASubscriptionResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "writeSmsToRuimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "deleteSmsOnRuimResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getDeviceIdentityResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "exitEmergencyCallbackModeResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getSmscAddressResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "setSmscAddressResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "reportSmsMemoryStatusResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getCdmaSubscriptionSourceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSubscriptionSource"
+        }
+    }
+
+    api: {
+        name: "requestIsimAuthenticationResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "acknowledgeIncomingGsmSmsWithPduResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "sendEnvelopeWithStatusResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIoResult"
+        }
+    }
+
+    api: {
+        name: "getVoiceRadioTechnologyResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioTechnology"
+        }
+    }
+
+    api: {
+        name: "getCellInfoListResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::CellInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setCellInfoListRateResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setInitialAttachApnResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getImsRegistrationStateResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::RadioTechnologyFamily"
+        }
+    }
+
+    api: {
+        name: "sendImsSmsResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SendSmsResult"
+        }
+    }
+
+    api: {
+        name: "iccTransmitApduBasicChannelResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIoResult"
+        }
+    }
+
+    api: {
+        name: "iccOpenLogicalChannelResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "int8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "iccCloseLogicalChannelResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "iccTransmitApduLogicalChannelResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIoResult"
+        }
+    }
+
+    api: {
+        name: "nvReadItemResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRING
+        }
+    }
+
+    api: {
+        name: "nvWriteItemResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "nvWriteCdmaPrlResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "nvResetConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setUiccSubscriptionResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "setDataAllowedResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getHardwareConfigResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::radio::V1_0::HardwareConfig"
+            }
+        }
+    }
+
+    api: {
+        name: "requestIccSimAuthenticationResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::IccIoResult"
+        }
+    }
+
+    api: {
+        name: "setDataProfileResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "requestShutdownResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+    }
+
+    api: {
+        name: "getRadioCapabilityResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioCapability"
+        }
+    }
+
+    api: {
+        name: "setRadioCapabilityResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioCapability"
+        }
+    }
+
+    api: {
+        name: "startLceServiceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::LceStatusInfo"
+        }
+    }
+
+    api: {
+        name: "stopLceServiceResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::LceStatusInfo"
+        }
+    }
+
+    api: {
+        name: "pullLceDataResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::LceDataInfo"
+        }
+    }
+
+    api: {
+        name: "getModemActivityInfoResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::ActivityStatsInfo"
+        }
+    }
+
+    api: {
+        name: "setAllowedCarriersResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "getAllowedCarriersResponse"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::RadioResponseInfo"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CarrierRestrictions"
+        }
+    }
+
+    api: {
+        name: "acknowledgeRequest"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+}
diff --git a/radio/1.0/vts/Sap.vts b/radio/1.0/vts/Sap.vts
new file mode 100644
index 0000000..23205d0
--- /dev/null
+++ b/radio/1.0/vts/Sap.vts
@@ -0,0 +1,107 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "ISap"
+
+package: "android.hardware.radio"
+
+import: "android.hardware.radio@1.0::ISapCallback"
+import: "android.hardware.radio@1.0::types"
+
+interface: {
+    api: {
+        name: "setCallback"
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "ISapCallback"
+            is_callback: true
+        }
+    }
+
+    api: {
+        name: "connectReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "disconnectReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "apduReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapApduType"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "transferAtrReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "powerReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "resetSimReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "transferCardReaderStatusReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "setTransferProtocolReq"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapTransferProtocol"
+        }
+    }
+
+}
diff --git a/radio/1.0/vts/SapCallback.vts b/radio/1.0/vts/SapCallback.vts
new file mode 100644
index 0000000..2e61ce6
--- /dev/null
+++ b/radio/1.0/vts/SapCallback.vts
@@ -0,0 +1,156 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "ISapCallback"
+
+package: "android.hardware.radio"
+
+import: "android.hardware.radio@1.0::types"
+
+interface: {
+    api: {
+        name: "connectResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapConnectRsp"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "disconnectResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "disconnectIndication"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapDisconnectType"
+        }
+    }
+
+    api: {
+        name: "apduResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "transferAtrResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+    }
+
+    api: {
+        name: "powerResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+    }
+
+    api: {
+        name: "resetSimResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+    }
+
+    api: {
+        name: "statusIndication"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapStatus"
+        }
+    }
+
+    api: {
+        name: "transferCardReaderStatusResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "errorResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "transferProtocolResponse"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::radio::V1_0::SapResultCode"
+        }
+    }
+
+}
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/__init__.py b/radio/1.0/vts/functional/vts/testcases/hal/radio/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/__init__.py
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/Android.mk b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/__init__.py b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/__init__.py
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/Android.mk b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/Android.mk
new file mode 100644
index 0000000..59f7c85
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := RadioHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/radio/hidl/host
+include test/vts/tools/build/Android.host_config.mk
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/AndroidTest.xml b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..a826d20
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?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.
+-->
+<configuration description="Config for VTS HAL Radio test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/Radio.vts->/data/local/tmp/spec/Radio.vts" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/RadioIndication.vts->/data/local/tmp/spec/RadioIndication.vts" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/RadioResponse.vts->/data/local/tmp/spec/RadioResponse.vts" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/Sap.vts->/data/local/tmp/spec/Sap.vts" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/SapCallback.vts->/data/local/tmp/spec/SapCallback.vts" />
+        <option name="push" value="spec/hardware/interfaces/radio/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="RadioHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/radio/hidl/host/RadioHidlTest" />
+    </test>
+</configuration>
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/RadioHidlTest.py b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/RadioHidlTest.py
new file mode 100644
index 0000000..33dac35
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/RadioHidlTest.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3.4
+#
+# 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.
+#
+
+import logging
+import time
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.profiling import profiling_utils
+
+
+class VehicleHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """A simple testcase for the VEHICLE HIDL HAL."""
+
+    def setUpClass(self):
+        """Creates a mirror and init vehicle hal."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        if self.enable_profiling:
+            profiling_utils.EnableVTSProfiling(self.dut.shell.one)
+
+        self.dut.hal.InitHidlHal(
+            target_type="radio",
+            target_basepaths=self.dut.libPaths,
+            target_version=1.0,
+            target_package="android.hardware.radio",
+            target_component_name="IRadio",
+            hw_binder_service_name="Radio",
+            bits=64 if self.dut.is64Bit else 32)
+
+        self.radio = self.dut.hal.radio  # shortcut
+        self.radio_types = self.dut.hal.radio.GetHidlTypeInterface("types")
+        logging.info("Radio types: %s", self.radio_types)
+
+    def tearDownClass(self):
+        """Disables the profiling.
+
+        If profiling is enabled for the test, collect the profiling data
+        and disable profiling after the test is done.
+        """
+        if self.enable_profiling:
+            profiling_trace_path = getattr(
+                self, self.VTS_PROFILING_TRACING_PATH, "")
+            self.ProcessAndUploadTraceData(self.dut, profiling_trace_path)
+            profiling_utils.DisableVTSProfiling(self.dut.shell.one)
+
+    def testHelloWorld(self):
+        logging.info('hello world')
+
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/__init__.py b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/radio/1.0/vts/functional/vts/testcases/hal/radio/hidl/host/__init__.py
diff --git a/radio/1.0/vts/types.vts b/radio/1.0/vts/types.vts
new file mode 100644
index 0000000..c11db63
--- /dev/null
+++ b/radio/1.0/vts/types.vts
@@ -0,0 +1,5532 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.radio"
+
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioConst"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CDMA_ALPHA_INFO_BUFFER_LENGTH"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "CDMA_NUMBER_INFO_BUFFER_LENGTH"
+        scalar_value: {
+            int32_t: 81
+        }
+        enumerator: "MAX_RILDS"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "MAX_SOCKET_NAME_LENGTH"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "MAX_CLIENT_ID_LENGTH"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "MAX_DEBUG_SOCKET_NAME_LENGTH"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "MAX_QEMU_PIPE_NAME_LENGTH"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "MAX_UUID_LENGTH"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "CARD_MAX_APPS"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "CDMA_MAX_NUMBER_OF_INFO_RECS"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "SS_INFO_MAX"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NUM_SERVICE_CLASSES"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "NUM_TX_POWER_LEVELS"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioCdmaSmsConst"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ADDRESS_MAX"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "SUBADDRESS_MAX"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "BEARER_DATA_MAX"
+        scalar_value: {
+            int32_t: 255
+        }
+        enumerator: "UDH_MAX_SND_SIZE"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "UDH_EO_DATA_SEGMENT_MAX"
+        scalar_value: {
+            int32_t: 131
+        }
+        enumerator: "MAX_UD_HEADERS"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "USER_DATA_MAX"
+        scalar_value: {
+            int32_t: 229
+        }
+        enumerator: "UDH_LARGE_PIC_SIZE"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "UDH_SMALL_PIC_SIZE"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "UDH_VAR_PIC_SIZE"
+        scalar_value: {
+            int32_t: 134
+        }
+        enumerator: "UDH_ANIM_NUM_BITMAPS"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "UDH_LARGE_BITMAP_SIZE"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "UDH_SMALL_BITMAP_SIZE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "UDH_OTHER_SIZE"
+        scalar_value: {
+            int32_t: 226
+        }
+        enumerator: "IP_ADDRESS_SIZE"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioError"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RADIO_NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "GENERIC_FAILURE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "PASSWORD_INCORRECT"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SIM_PIN2"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SIM_PUK2"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "REQUEST_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "CANCELLED"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "OP_NOT_ALLOWED_DURING_VOICE_CALL"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "OP_NOT_ALLOWED_BEFORE_REG_TO_NW"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "SMS_SEND_FAIL_RETRY"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "SIM_ABSENT"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "SUBSCRIPTION_NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "MODE_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "FDN_CHECK_FAILURE"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "ILLEGAL_SIM_OR_ME"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "MISSING_RESOURCE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "NO_SUCH_ELEMENT"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "DIAL_MODIFIED_TO_USSD"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "DIAL_MODIFIED_TO_SS"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "DIAL_MODIFIED_TO_DIAL"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "USSD_MODIFIED_TO_DIAL"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "USSD_MODIFIED_TO_SS"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "USSD_MODIFIED_TO_USSD"
+        scalar_value: {
+            int32_t: 23
+        }
+        enumerator: "SS_MODIFIED_TO_DIAL"
+        scalar_value: {
+            int32_t: 24
+        }
+        enumerator: "SS_MODIFIED_TO_USSD"
+        scalar_value: {
+            int32_t: 25
+        }
+        enumerator: "SUBSCRIPTION_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "SS_MODIFIED_TO_SS"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "LCE_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "NO_MEMORY"
+        scalar_value: {
+            int32_t: 37
+        }
+        enumerator: "INTERNAL_ERR"
+        scalar_value: {
+            int32_t: 38
+        }
+        enumerator: "SYSTEM_ERR"
+        scalar_value: {
+            int32_t: 39
+        }
+        enumerator: "MODEM_ERR"
+        scalar_value: {
+            int32_t: 40
+        }
+        enumerator: "INVALID_STATE"
+        scalar_value: {
+            int32_t: 41
+        }
+        enumerator: "NO_RESOURCES"
+        scalar_value: {
+            int32_t: 42
+        }
+        enumerator: "SIM_ERR"
+        scalar_value: {
+            int32_t: 43
+        }
+        enumerator: "INVALID_ARGUMENTS"
+        scalar_value: {
+            int32_t: 44
+        }
+        enumerator: "INVALID_SIM_STATE"
+        scalar_value: {
+            int32_t: 45
+        }
+        enumerator: "INVALID_MODEM_STATE"
+        scalar_value: {
+            int32_t: 46
+        }
+        enumerator: "INVALID_CALL_ID"
+        scalar_value: {
+            int32_t: 47
+        }
+        enumerator: "NO_SMS_TO_ACK"
+        scalar_value: {
+            int32_t: 48
+        }
+        enumerator: "NETWORK_ERR"
+        scalar_value: {
+            int32_t: 49
+        }
+        enumerator: "REQUEST_RATE_LIMITED"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "SIM_BUSY"
+        scalar_value: {
+            int32_t: 51
+        }
+        enumerator: "SIM_FULL"
+        scalar_value: {
+            int32_t: 52
+        }
+        enumerator: "NETWORK_REJECT"
+        scalar_value: {
+            int32_t: 53
+        }
+        enumerator: "OPERATION_NOT_ALLOWED"
+        scalar_value: {
+            int32_t: 54
+        }
+        enumerator: "EMPTY_RECORD"
+        scalar_value: {
+            int32_t: 55
+        }
+        enumerator: "INVALID_SMS_FORMAT"
+        scalar_value: {
+            int32_t: 56
+        }
+        enumerator: "ENCODING_ERR"
+        scalar_value: {
+            int32_t: 57
+        }
+        enumerator: "INVALID_SMSC_ADDRESS"
+        scalar_value: {
+            int32_t: 58
+        }
+        enumerator: "NO_SUCH_ENTRY"
+        scalar_value: {
+            int32_t: 59
+        }
+        enumerator: "NETWORK_NOT_READY"
+        scalar_value: {
+            int32_t: 60
+        }
+        enumerator: "NOT_PROVISIONED"
+        scalar_value: {
+            int32_t: 61
+        }
+        enumerator: "NO_SUBSCRIPTION"
+        scalar_value: {
+            int32_t: 62
+        }
+        enumerator: "NO_NETWORK_FOUND"
+        scalar_value: {
+            int32_t: 63
+        }
+        enumerator: "DEVICE_IN_USE"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "ABORTED"
+        scalar_value: {
+            int32_t: 65
+        }
+        enumerator: "INVALID_RESPONSE"
+        scalar_value: {
+            int32_t: 66
+        }
+        enumerator: "OEM_ERROR_1"
+        scalar_value: {
+            int32_t: 501
+        }
+        enumerator: "OEM_ERROR_2"
+        scalar_value: {
+            int32_t: 502
+        }
+        enumerator: "OEM_ERROR_3"
+        scalar_value: {
+            int32_t: 503
+        }
+        enumerator: "OEM_ERROR_4"
+        scalar_value: {
+            int32_t: 504
+        }
+        enumerator: "OEM_ERROR_5"
+        scalar_value: {
+            int32_t: 505
+        }
+        enumerator: "OEM_ERROR_6"
+        scalar_value: {
+            int32_t: 506
+        }
+        enumerator: "OEM_ERROR_7"
+        scalar_value: {
+            int32_t: 507
+        }
+        enumerator: "OEM_ERROR_8"
+        scalar_value: {
+            int32_t: 508
+        }
+        enumerator: "OEM_ERROR_9"
+        scalar_value: {
+            int32_t: 509
+        }
+        enumerator: "OEM_ERROR_10"
+        scalar_value: {
+            int32_t: 510
+        }
+        enumerator: "OEM_ERROR_11"
+        scalar_value: {
+            int32_t: 511
+        }
+        enumerator: "OEM_ERROR_12"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "OEM_ERROR_13"
+        scalar_value: {
+            int32_t: 513
+        }
+        enumerator: "OEM_ERROR_14"
+        scalar_value: {
+            int32_t: 514
+        }
+        enumerator: "OEM_ERROR_15"
+        scalar_value: {
+            int32_t: 515
+        }
+        enumerator: "OEM_ERROR_16"
+        scalar_value: {
+            int32_t: 516
+        }
+        enumerator: "OEM_ERROR_17"
+        scalar_value: {
+            int32_t: 517
+        }
+        enumerator: "OEM_ERROR_18"
+        scalar_value: {
+            int32_t: 518
+        }
+        enumerator: "OEM_ERROR_19"
+        scalar_value: {
+            int32_t: 519
+        }
+        enumerator: "OEM_ERROR_20"
+        scalar_value: {
+            int32_t: 520
+        }
+        enumerator: "OEM_ERROR_21"
+        scalar_value: {
+            int32_t: 521
+        }
+        enumerator: "OEM_ERROR_22"
+        scalar_value: {
+            int32_t: 522
+        }
+        enumerator: "OEM_ERROR_23"
+        scalar_value: {
+            int32_t: 523
+        }
+        enumerator: "OEM_ERROR_24"
+        scalar_value: {
+            int32_t: 524
+        }
+        enumerator: "OEM_ERROR_25"
+        scalar_value: {
+            int32_t: 525
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioResponseType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SOLICITED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SOLICITED_ACK"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SOLICITED_ACK_EXP"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioIndicationType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNSOLICITED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "UNSOLICITED_ACK_EXP"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RestrictedState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CS_EMERGENCY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CS_NORMAL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CS_ALL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "PS_ALL"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CardState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ABSENT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "PRESENT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ERROR"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "RESTRICTED"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::PinState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ENABLED_NOT_VERIFIED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ENABLED_VERIFIED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "DISABLED"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ENABLED_BLOCKED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ENABLED_PERM_BLOCKED"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::AppType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SIM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "USIM"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "RUIM"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CSIM"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ISIM"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::AppState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DETECTED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "PIN"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "PUK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SUBSCRIPTION_PERSO"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "READY"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::PersoSubstate"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "IN_PROGRESS"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "READY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SIM_NETWORK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SIM_NETWORK_SUBSET"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SIM_CORPORATE"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "SIM_SERVICE_PROVIDER"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "SIM_SIM"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "SIM_NETWORK_PUK"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "SIM_NETWORK_SUBSET_PUK"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "SIM_CORPORATE_PUK"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "SIM_SERVICE_PROVIDER_PUK"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "SIM_SIM_PUK"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "RUIM_NETWORK1"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "RUIM_NETWORK2"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "RUIM_HRPD"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "RUIM_CORPORATE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "RUIM_SERVICE_PROVIDER"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "RUIM_RUIM"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "RUIM_NETWORK1_PUK"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "RUIM_NETWORK2_PUK"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "RUIM_HRPD_PUK"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "RUIM_CORPORATE_PUK"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "RUIM_SERVICE_PROVIDER_PUK"
+        scalar_value: {
+            int32_t: 23
+        }
+        enumerator: "RUIM_RUIM_PUK"
+        scalar_value: {
+            int32_t: 24
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OFF"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "UNAVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ON"
+        scalar_value: {
+            int32_t: 10
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapConnectRsp"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CONNECT_FAILURE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MSG_SIZE_TOO_LARGE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "MSG_SIZE_TOO_SMALL"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CONNECT_OK_CALL_ONGOING"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapDisconnectType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GRACEFUL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "IMMEDIATE"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapApduType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "APDU"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "APDU7816"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapResultCode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "GENERIC_FAILURE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CARD_NOT_ACCESSSIBLE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CARD_ALREADY_POWERED_OFF"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CARD_REMOVED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CARD_ALREADY_POWERED_ON"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "DATA_NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 7
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN_ERROR"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CARD_RESET"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CARD_NOT_ACCESSIBLE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CARD_REMOVED"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CARD_INSERTED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "RECOVERED"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SapTransferProtocol"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "T0"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "T1"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CallState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ACTIVE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "HOLDING"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DIALING"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ALERTING"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "INCOMING"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "WAITING"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::UusType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "TYPE1_IMPLICIT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TYPE1_REQUIRED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TYPE1_NOT_REQUIRED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "TYPE2_REQUIRED"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "TYPE2_NOT_REQUIRED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "TYPE3_REQUIRED"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "TYPE3_NOT_REQUIRED"
+        scalar_value: {
+            int32_t: 6
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::UusDcs"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "USP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "OSIHLP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "X244"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "RMCF"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "IA5C"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CallPresentation"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ALLOWED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RESTRICTED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "PAYPHONE"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::Clir"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INVOCATION"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SUPPRESSION"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LastCallFailCause"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNOBTAINABLE_NUMBER"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NO_ROUTE_TO_DESTINATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CHANNEL_UNACCEPTABLE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "OPERATOR_DETERMINED_BARRING"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "BUSY"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "NO_USER_RESPONDING"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "NO_ANSWER_FROM_USER"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "CALL_REJECTED"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "NUMBER_CHANGED"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "PREEMPTION"
+        scalar_value: {
+            int32_t: 25
+        }
+        enumerator: "DESTINATION_OUT_OF_ORDER"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "INVALID_NUMBER_FORMAT"
+        scalar_value: {
+            int32_t: 28
+        }
+        enumerator: "FACILITY_REJECTED"
+        scalar_value: {
+            int32_t: 29
+        }
+        enumerator: "RESP_TO_STATUS_ENQUIRY"
+        scalar_value: {
+            int32_t: 30
+        }
+        enumerator: "NORMAL_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "CONGESTION"
+        scalar_value: {
+            int32_t: 34
+        }
+        enumerator: "NETWORK_OUT_OF_ORDER"
+        scalar_value: {
+            int32_t: 38
+        }
+        enumerator: "TEMPORARY_FAILURE"
+        scalar_value: {
+            int32_t: 41
+        }
+        enumerator: "SWITCHING_EQUIPMENT_CONGESTION"
+        scalar_value: {
+            int32_t: 42
+        }
+        enumerator: "ACCESS_INFORMATION_DISCARDED"
+        scalar_value: {
+            int32_t: 43
+        }
+        enumerator: "REQUESTED_CIRCUIT_OR_CHANNEL_NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 44
+        }
+        enumerator: "RESOURCES_UNAVAILABLE_OR_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 47
+        }
+        enumerator: "QOS_UNAVAILABLE"
+        scalar_value: {
+            int32_t: 49
+        }
+        enumerator: "REQUESTED_FACILITY_NOT_SUBSCRIBED"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "INCOMING_CALLS_BARRED_WITHIN_CUG"
+        scalar_value: {
+            int32_t: 55
+        }
+        enumerator: "BEARER_CAPABILITY_NOT_AUTHORIZED"
+        scalar_value: {
+            int32_t: 57
+        }
+        enumerator: "BEARER_CAPABILITY_UNAVAILABLE"
+        scalar_value: {
+            int32_t: 58
+        }
+        enumerator: "SERVICE_OPTION_NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 63
+        }
+        enumerator: "BEARER_SERVICE_NOT_IMPLEMENTED"
+        scalar_value: {
+            int32_t: 65
+        }
+        enumerator: "ACM_LIMIT_EXCEEDED"
+        scalar_value: {
+            int32_t: 68
+        }
+        enumerator: "REQUESTED_FACILITY_NOT_IMPLEMENTED"
+        scalar_value: {
+            int32_t: 69
+        }
+        enumerator: "ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE"
+        scalar_value: {
+            int32_t: 70
+        }
+        enumerator: "SERVICE_OR_OPTION_NOT_IMPLEMENTED"
+        scalar_value: {
+            int32_t: 79
+        }
+        enumerator: "INVALID_TRANSACTION_IDENTIFIER"
+        scalar_value: {
+            int32_t: 81
+        }
+        enumerator: "USER_NOT_MEMBER_OF_CUG"
+        scalar_value: {
+            int32_t: 87
+        }
+        enumerator: "INCOMPATIBLE_DESTINATION"
+        scalar_value: {
+            int32_t: 88
+        }
+        enumerator: "INVALID_TRANSIT_NW_SELECTION"
+        scalar_value: {
+            int32_t: 91
+        }
+        enumerator: "SEMANTICALLY_INCORRECT_MESSAGE"
+        scalar_value: {
+            int32_t: 95
+        }
+        enumerator: "INVALID_MANDATORY_INFORMATION"
+        scalar_value: {
+            int32_t: 96
+        }
+        enumerator: "MESSAGE_TYPE_NON_IMPLEMENTED"
+        scalar_value: {
+            int32_t: 97
+        }
+        enumerator: "MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"
+        scalar_value: {
+            int32_t: 98
+        }
+        enumerator: "INFORMATION_ELEMENT_NON_EXISTENT"
+        scalar_value: {
+            int32_t: 99
+        }
+        enumerator: "CONDITIONAL_IE_ERROR"
+        scalar_value: {
+            int32_t: 100
+        }
+        enumerator: "MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE"
+        scalar_value: {
+            int32_t: 101
+        }
+        enumerator: "RECOVERY_ON_TIMER_EXPIRED"
+        scalar_value: {
+            int32_t: 102
+        }
+        enumerator: "PROTOCOL_ERROR_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 111
+        }
+        enumerator: "INTERWORKING_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 127
+        }
+        enumerator: "CALL_BARRED"
+        scalar_value: {
+            int32_t: 240
+        }
+        enumerator: "FDN_BLOCKED"
+        scalar_value: {
+            int32_t: 241
+        }
+        enumerator: "IMSI_UNKNOWN_IN_VLR"
+        scalar_value: {
+            int32_t: 242
+        }
+        enumerator: "IMEI_NOT_ACCEPTED"
+        scalar_value: {
+            int32_t: 243
+        }
+        enumerator: "DIAL_MODIFIED_TO_USSD"
+        scalar_value: {
+            int32_t: 244
+        }
+        enumerator: "DIAL_MODIFIED_TO_SS"
+        scalar_value: {
+            int32_t: 245
+        }
+        enumerator: "DIAL_MODIFIED_TO_DIAL"
+        scalar_value: {
+            int32_t: 246
+        }
+        enumerator: "CDMA_LOCKED_UNTIL_POWER_CYCLE"
+        scalar_value: {
+            int32_t: 1000
+        }
+        enumerator: "CDMA_DROP"
+        scalar_value: {
+            int32_t: 1001
+        }
+        enumerator: "CDMA_INTERCEPT"
+        scalar_value: {
+            int32_t: 1002
+        }
+        enumerator: "CDMA_REORDER"
+        scalar_value: {
+            int32_t: 1003
+        }
+        enumerator: "CDMA_SO_REJECT"
+        scalar_value: {
+            int32_t: 1004
+        }
+        enumerator: "CDMA_RETRY_ORDER"
+        scalar_value: {
+            int32_t: 1005
+        }
+        enumerator: "CDMA_ACCESS_FAILURE"
+        scalar_value: {
+            int32_t: 1006
+        }
+        enumerator: "CDMA_PREEMPTED"
+        scalar_value: {
+            int32_t: 1007
+        }
+        enumerator: "CDMA_NOT_EMERGENCY"
+        scalar_value: {
+            int32_t: 1008
+        }
+        enumerator: "CDMA_ACCESS_BLOCKED"
+        scalar_value: {
+            int32_t: 1009
+        }
+        enumerator: "ERROR_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 65535
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::DataCallFailCause"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "OPERATOR_BARRED"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "NAS_SIGNALLING"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "INSUFFICIENT_RESOURCES"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "MISSING_UKNOWN_APN"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "UNKNOWN_PDP_ADDRESS_TYPE"
+        scalar_value: {
+            int32_t: 28
+        }
+        enumerator: "USER_AUTHENTICATION"
+        scalar_value: {
+            int32_t: 29
+        }
+        enumerator: "ACTIVATION_REJECT_GGSN"
+        scalar_value: {
+            int32_t: 30
+        }
+        enumerator: "ACTIVATION_REJECT_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "SERVICE_OPTION_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "SERVICE_OPTION_NOT_SUBSCRIBED"
+        scalar_value: {
+            int32_t: 33
+        }
+        enumerator: "SERVICE_OPTION_OUT_OF_ORDER"
+        scalar_value: {
+            int32_t: 34
+        }
+        enumerator: "NSAPI_IN_USE"
+        scalar_value: {
+            int32_t: 35
+        }
+        enumerator: "REGULAR_DEACTIVATION"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "QOS_NOT_ACCEPTED"
+        scalar_value: {
+            int32_t: 37
+        }
+        enumerator: "NETWORK_FAILURE"
+        scalar_value: {
+            int32_t: 38
+        }
+        enumerator: "UMTS_REACTIVATION_REQ"
+        scalar_value: {
+            int32_t: 39
+        }
+        enumerator: "FEATURE_NOT_SUPP"
+        scalar_value: {
+            int32_t: 40
+        }
+        enumerator: "TFT_SEMANTIC_ERROR"
+        scalar_value: {
+            int32_t: 41
+        }
+        enumerator: "TFT_SYTAX_ERROR"
+        scalar_value: {
+            int32_t: 42
+        }
+        enumerator: "UNKNOWN_PDP_CONTEXT"
+        scalar_value: {
+            int32_t: 43
+        }
+        enumerator: "FILTER_SEMANTIC_ERROR"
+        scalar_value: {
+            int32_t: 44
+        }
+        enumerator: "FILTER_SYTAX_ERROR"
+        scalar_value: {
+            int32_t: 45
+        }
+        enumerator: "PDP_WITHOUT_ACTIVE_TFT"
+        scalar_value: {
+            int32_t: 46
+        }
+        enumerator: "ONLY_IPV4_ALLOWED"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "ONLY_IPV6_ALLOWED"
+        scalar_value: {
+            int32_t: 51
+        }
+        enumerator: "ONLY_SINGLE_BEARER_ALLOWED"
+        scalar_value: {
+            int32_t: 52
+        }
+        enumerator: "ESM_INFO_NOT_RECEIVED"
+        scalar_value: {
+            int32_t: 53
+        }
+        enumerator: "PDN_CONN_DOES_NOT_EXIST"
+        scalar_value: {
+            int32_t: 54
+        }
+        enumerator: "MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED"
+        scalar_value: {
+            int32_t: 55
+        }
+        enumerator: "MAX_ACTIVE_PDP_CONTEXT_REACHED"
+        scalar_value: {
+            int32_t: 65
+        }
+        enumerator: "UNSUPPORTED_APN_IN_CURRENT_PLMN"
+        scalar_value: {
+            int32_t: 66
+        }
+        enumerator: "INVALID_TRANSACTION_ID"
+        scalar_value: {
+            int32_t: 81
+        }
+        enumerator: "MESSAGE_INCORRECT_SEMANTIC"
+        scalar_value: {
+            int32_t: 95
+        }
+        enumerator: "INVALID_MANDATORY_INFO"
+        scalar_value: {
+            int32_t: 96
+        }
+        enumerator: "MESSAGE_TYPE_UNSUPPORTED"
+        scalar_value: {
+            int32_t: 97
+        }
+        enumerator: "MSG_TYPE_NONCOMPATIBLE_STATE"
+        scalar_value: {
+            int32_t: 98
+        }
+        enumerator: "UNKNOWN_INFO_ELEMENT"
+        scalar_value: {
+            int32_t: 99
+        }
+        enumerator: "CONDITIONAL_IE_ERROR"
+        scalar_value: {
+            int32_t: 100
+        }
+        enumerator: "MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE"
+        scalar_value: {
+            int32_t: 101
+        }
+        enumerator: "PROTOCOL_ERRORS"
+        scalar_value: {
+            int32_t: 111
+        }
+        enumerator: "APN_TYPE_CONFLICT"
+        scalar_value: {
+            int32_t: 112
+        }
+        enumerator: "INVALID_PCSCF_ADDR"
+        scalar_value: {
+            int32_t: 113
+        }
+        enumerator: "INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN"
+        scalar_value: {
+            int32_t: 114
+        }
+        enumerator: "EMM_ACCESS_BARRED"
+        scalar_value: {
+            int32_t: 115
+        }
+        enumerator: "EMERGENCY_IFACE_ONLY"
+        scalar_value: {
+            int32_t: 116
+        }
+        enumerator: "IFACE_MISMATCH"
+        scalar_value: {
+            int32_t: 117
+        }
+        enumerator: "COMPANION_IFACE_IN_USE"
+        scalar_value: {
+            int32_t: 118
+        }
+        enumerator: "IP_ADDRESS_MISMATCH"
+        scalar_value: {
+            int32_t: 119
+        }
+        enumerator: "IFACE_AND_POL_FAMILY_MISMATCH"
+        scalar_value: {
+            int32_t: 120
+        }
+        enumerator: "EMM_ACCESS_BARRED_INFINITE_RETRY"
+        scalar_value: {
+            int32_t: 121
+        }
+        enumerator: "AUTH_FAILURE_ON_EMERGENCY_CALL"
+        scalar_value: {
+            int32_t: 122
+        }
+        enumerator: "OEM_DCFAILCAUSE_1"
+        scalar_value: {
+            int32_t: 4097
+        }
+        enumerator: "OEM_DCFAILCAUSE_2"
+        scalar_value: {
+            int32_t: 4098
+        }
+        enumerator: "OEM_DCFAILCAUSE_3"
+        scalar_value: {
+            int32_t: 4099
+        }
+        enumerator: "OEM_DCFAILCAUSE_4"
+        scalar_value: {
+            int32_t: 4100
+        }
+        enumerator: "OEM_DCFAILCAUSE_5"
+        scalar_value: {
+            int32_t: 4101
+        }
+        enumerator: "OEM_DCFAILCAUSE_6"
+        scalar_value: {
+            int32_t: 4102
+        }
+        enumerator: "OEM_DCFAILCAUSE_7"
+        scalar_value: {
+            int32_t: 4103
+        }
+        enumerator: "OEM_DCFAILCAUSE_8"
+        scalar_value: {
+            int32_t: 4104
+        }
+        enumerator: "OEM_DCFAILCAUSE_9"
+        scalar_value: {
+            int32_t: 4105
+        }
+        enumerator: "OEM_DCFAILCAUSE_10"
+        scalar_value: {
+            int32_t: 4106
+        }
+        enumerator: "OEM_DCFAILCAUSE_11"
+        scalar_value: {
+            int32_t: 4107
+        }
+        enumerator: "OEM_DCFAILCAUSE_12"
+        scalar_value: {
+            int32_t: 4108
+        }
+        enumerator: "OEM_DCFAILCAUSE_13"
+        scalar_value: {
+            int32_t: 4109
+        }
+        enumerator: "OEM_DCFAILCAUSE_14"
+        scalar_value: {
+            int32_t: 4110
+        }
+        enumerator: "OEM_DCFAILCAUSE_15"
+        scalar_value: {
+            int32_t: 4111
+        }
+        enumerator: "VOICE_REGISTRATION_FAIL"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "DATA_REGISTRATION_FAIL"
+        scalar_value: {
+            int32_t: -2
+        }
+        enumerator: "SIGNAL_LOST"
+        scalar_value: {
+            int32_t: -3
+        }
+        enumerator: "PREF_RADIO_TECH_CHANGED"
+        scalar_value: {
+            int32_t: -4
+        }
+        enumerator: "RADIO_POWER_OFF"
+        scalar_value: {
+            int32_t: -5
+        }
+        enumerator: "TETHERED_CALL_ACTIVE"
+        scalar_value: {
+            int32_t: -6
+        }
+        enumerator: "ERROR_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 65535
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RegState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NOT_REG_MT_NOT_SEARCHING_OP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "REG_HOME"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NOT_REG_MT_SEARCHING_OP"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "REG_DENIED"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "REG_ROAMING"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "NOT_REG_MT_NOT_SEARCHING_OP_EM"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "NOT_REG_MT_SEARCHING_OP_EM"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "REG_DENIED_EM"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "UNKNOWN_EM"
+        scalar_value: {
+            int32_t: 9
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioTechnology"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "GPRS"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "EDGE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "UMTS"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "IS95A"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "IS95B"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "ONE_X_RTT"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "EVDO_0"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "EVDO_A"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "HSDPA"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "HSUPA"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "HSPA"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "EVDO_B"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "EHRPD"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "LTE"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "HSPAP"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "GSM"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "TD_SCDMA"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "IWLAN"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "LTE_CA"
+        scalar_value: {
+            int32_t: 19
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::DataProfile"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TETHERED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "IMS"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FOTA"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CBS"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "OEM_BASE"
+        scalar_value: {
+            int32_t: 1000
+        }
+        enumerator: "INVALID"
+        scalar_value: {
+            int32_t: -1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SmsAcknowledgeFailCause"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "MEMORY_CAPAPCITY_EXCEEDED"
+        scalar_value: {
+            int32_t: 211
+        }
+        enumerator: "UNSPECIFIED_ERROR"
+        scalar_value: {
+            int32_t: 255
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CallForwardInfoStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DISABLE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ENABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "INTERROGATE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "REGISTRATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ERASURE"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::ClipStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CLIP_PROVISIONED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CLIP_UNPROVISIONED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "UNKOWN"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SmsWriteArgsStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "REC_UNREAD"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "REC_READ"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "STO_UNSENT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "STO_SENT"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioBandMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "BAND_MODE_UNSPECIFIED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "BAND_MODE_EURO"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "BAND_MODE_USA"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "BAND_MODE_JPN"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "BAND_MODE_AUS"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "BAND_MODE_AUS_2"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "BAND_MODE_CELL_800"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "BAND_MODE_PCS"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "BAND_MODE_JTACS"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "BAND_MODE_KOREA_PCS"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "BAND_MODE_5_450M"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "BAND_MODE_IMT2000"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "BAND_MODE_7_700M_2"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "BAND_MODE_8_1800M"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "BAND_MODE_9_900M"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "BAND_MODE_10_800M_2"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "BAND_MODE_EURO_PAMR_400M"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "BAND_MODE_AWS"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "BAND_MODE_USA_2500M"
+        scalar_value: {
+            int32_t: 18
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::OperatorStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CURRENT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FORBIDDEN"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::PreferredNetworkType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GSM_WCDMA"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "GSM_ONLY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "WCDMA"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "GSM_WCDMA_AUTO"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CDMA_EVDO_AUTO"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CDMA_ONLY"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "EVDO_ONLY"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "GSM_WCDMA_CDMA_EVDO_AUTO"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "LTE_CDMA_EVDO"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "LTE_GSM_WCDMA"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "LTE_CMDA_EVDO_GSM_WCDMA"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "LTE_ONLY"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "LTE_WCDMA"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "TD_SCDMA_ONLY"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "TD_SCDMA_WCDMA"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "TD_SCDMA_LTE"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "TD_SCDMA_GSM"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "TD_SCDMA_GSM_LTE"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "TD_SCDMA_GSM_WCDMA"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "TD_SCDMA_WCDMA_LTE"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "TD_SCDMA_GSM_WCDMA_LTE"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "TD_SCDMA_GSM_WCDMA_CDMA_EVDO_AUTO"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA"
+        scalar_value: {
+            int32_t: 22
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSubscriptionSource"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "RUIM_SIM"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NV"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaRoamingType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "HOME_NETWORK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AFFILIATED_ROAM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ANY_ROAM"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::TtyMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OFF"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FULL"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "HCO"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VCO"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::NvItem"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CDMA_MEID"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CDMA_MIN"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CDMA_MDN"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CDMA_ACCOLC"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "DEVICE_MSL"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "RTN_RECONDITIONED_STATUS"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "RTN_ACTIVATION_DATE"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "RTN_LIFE_TIMER"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "RTN_LIFE_CALLS"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "RTN_LIFE_DATA_TX"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "RTN_LIFE_DATA_RX"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "OMADM_HFA_LEVEL"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "MIP_PROFILE_NAI"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "MIP_PROFILE_HOME_ADDRESS"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "MIP_PROFILE_AAA_AUTH"
+        scalar_value: {
+            int32_t: 33
+        }
+        enumerator: "MIP_PROFILE_HA_AUTH"
+        scalar_value: {
+            int32_t: 34
+        }
+        enumerator: "MIP_PROFILE_PRI_HA_ADDR"
+        scalar_value: {
+            int32_t: 35
+        }
+        enumerator: "MIP_PROFILE_SEC_HA_ADDR"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "MIP_PROFILE_REV_TUN_PREF"
+        scalar_value: {
+            int32_t: 37
+        }
+        enumerator: "MIP_PROFILE_HA_SPI"
+        scalar_value: {
+            int32_t: 38
+        }
+        enumerator: "MIP_PROFILE_AAA_SPI"
+        scalar_value: {
+            int32_t: 39
+        }
+        enumerator: "MIP_PROFILE_MN_HA_SS"
+        scalar_value: {
+            int32_t: 40
+        }
+        enumerator: "MIP_PROFILE_MN_AAA_SS"
+        scalar_value: {
+            int32_t: 41
+        }
+        enumerator: "CDMA_PRL_VERSION"
+        scalar_value: {
+            int32_t: 51
+        }
+        enumerator: "CDMA_BC10"
+        scalar_value: {
+            int32_t: 52
+        }
+        enumerator: "CDMA_BC14"
+        scalar_value: {
+            int32_t: 53
+        }
+        enumerator: "CDMA_SO68"
+        scalar_value: {
+            int32_t: 54
+        }
+        enumerator: "CDMA_SO73_COP0"
+        scalar_value: {
+            int32_t: 55
+        }
+        enumerator: "CDMA_SO73_COP1TO7"
+        scalar_value: {
+            int32_t: 56
+        }
+        enumerator: "CDMA_1X_ADVANCED_ENABLED"
+        scalar_value: {
+            int32_t: 57
+        }
+        enumerator: "CDMA_EHRPD_ENABLED"
+        scalar_value: {
+            int32_t: 58
+        }
+        enumerator: "CDMA_EHRPD_FORCED"
+        scalar_value: {
+            int32_t: 59
+        }
+        enumerator: "LTE_BAND_ENABLE_25"
+        scalar_value: {
+            int32_t: 71
+        }
+        enumerator: "LTE_BAND_ENABLE_26"
+        scalar_value: {
+            int32_t: 72
+        }
+        enumerator: "LTE_BAND_ENABLE_41"
+        scalar_value: {
+            int32_t: 73
+        }
+        enumerator: "LTE_SCAN_PRIORITY_25"
+        scalar_value: {
+            int32_t: 74
+        }
+        enumerator: "LTE_SCAN_PRIORITY_26"
+        scalar_value: {
+            int32_t: 75
+        }
+        enumerator: "LTE_SCAN_PRIORITY_41"
+        scalar_value: {
+            int32_t: 76
+        }
+        enumerator: "LTE_HIDDEN_BAND_PRIORITY_25"
+        scalar_value: {
+            int32_t: 77
+        }
+        enumerator: "LTE_HIDDEN_BAND_PRIORITY_26"
+        scalar_value: {
+            int32_t: 78
+        }
+        enumerator: "LTE_HIDDEN_BAND_PRIORITY_41"
+        scalar_value: {
+            int32_t: 79
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::ResetNvType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "RELOAD"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ERASE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "FACORY_RESET"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::HardwareConfigType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "MODEM"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SIM"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::HardwareConfigState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ENABLED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "STANDBY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DISABLED"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LceStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "STOPPED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ACTIVE"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CarrierMatchType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ALL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SPN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "IMSI_PREFIX"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "GID1"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "GID2"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::NeighboringCell"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cid"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "rssi"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsDigitMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FOUR_BIT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "EIGHT_BIT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsNumberMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NOT_DATA_NETWORK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DATA_NETWORK"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsNumberType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INTERNATIONAL_OR_DATA_IP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NATIONAL_OR_INTERNET_MAIL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "NETWORK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SUBSCRIBER"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ALPHANUMERIC"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "ABBREVIATED"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "RESERVED_7"
+        scalar_value: {
+            int32_t: 7
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsNumberPlan"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TELEPHONY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "RESERVED_2"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "DATA"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "TELEX"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "RESERVED_5"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "RESERVED_6"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "RESERVED_7"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "RESERVED_8"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "PRIVATE"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "RESERVED_10"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "RESERVED_11"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "RESERVED_12"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "RESERVED_13"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "RESERVED_14"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "RESERVED_15"
+        scalar_value: {
+            int32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsSubaddressType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NSAP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "USER_SPECIFIED"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsErrorClass"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NO_ERROR"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ERROR"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsWriteArgsStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "REC_UNREAD"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "REC_READ"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "STO_UNSENT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "STO_SENT"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GSM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CDMA"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "LTE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "WCDMA"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "TD_SCDMA"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::TimeStampType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ANTENNA"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MODEM"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "OEM_RIL"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "JAVA_RIL"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::ApnAuthType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NO_PAP_NO_CHAP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "PAP_NO_CHAP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NO_PAP_CHAP"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "PAP_CHAP"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioTechnologyFamily"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "THREE_GPP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "THREE_GPP2"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioCapabilityPhase"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CONFIGURED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "START"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "APPLY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "UNSOL_RSP"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "FINISH"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioCapabilityStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "FAIL"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioAccessFamily"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "GPRS"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "EDGE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "UMTS"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "IS95A"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "IS95B"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "ONE_X_RTT"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "EVDO_0"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "EVDO_A"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "HSDPA"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "HSUPA"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "HSPA"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "EVDO_B"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "EHRPD"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "LTE"
+        scalar_value: {
+            int32_t: 16384
+        }
+        enumerator: "HSPAP"
+        scalar_value: {
+            int32_t: 32768
+        }
+        enumerator: "GSM"
+        scalar_value: {
+            int32_t: 65536
+        }
+        enumerator: "TD_SCDMA"
+        scalar_value: {
+            int32_t: 131072
+        }
+        enumerator: "LTE_CA"
+        scalar_value: {
+            int32_t: 524288
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::UssdModeType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NOTIFY"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "REQUEST"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NW_RELEASE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "LOCAL_CLIENT"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NW_TIMEOUT"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SimRefreshType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SIM_FILE_UPDATE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SIM_INIT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SIM_RESET"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SrvccState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "HANDOVER_STARTED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "HANDOVER_COMPLETED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "HANDOVER_FAILED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "HANDOVER_CANCELED"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::UiccSubActStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEACTIVATE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ACTIVATE"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SubscriptionType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUBSCRIPTION_1"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SUBSCRIPTION_2"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SUBSCRIPTION_3"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::DataProfileInfoType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "COMMON"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "THREE_GPP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "THREE_GPP2"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::PhoneRestrictedState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CS_EMERGENCY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CS_NORMAL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CS_ALL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "PS_ALL"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberPresentation"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ALLOWED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RESTRICTED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INTERNATIONAL"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NATIONAL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "NETWORK_SPECIFIC"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SUBSCRIBER"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberPlan"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ISDN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DATA"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "TELEX"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NATIONAL"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "PRIVATE"
+        scalar_value: {
+            int32_t: 9
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaOtaProvisionStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SPL_UNLOCKED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SPC_RETRIES_EXCEEDED"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "A_KEY_EXCHANGED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SSD_UPDATED"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "NAM_DOWNLOADED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "MDN_DOWNLOADED"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "IMSI_DOWNLOADED"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "PRL_DOWNLOADED"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "COMMITTED"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "OTAPA_STARTED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "OTAPA_STOPPED"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "OTAPA_ABORTED"
+        scalar_value: {
+            int32_t: 11
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaInfoRecName"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DISPLAY"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CALLED_PARTY_NUMBER"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CALLING_PARTY_NUMBER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CONNECTED_NUMBER"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SIGNAL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "REDIRECTING_NUMBER"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "LINE_CONTROL"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "EXTENDED_DISPLAY"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "T53_CLIR"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "T53_RELEASE"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "T53_AUDIO_CONTROL"
+        scalar_value: {
+            int32_t: 10
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaRedirectingReason"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CALL_FORWARDING_BUSY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CALL_FORWARDING_NO_REPLY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CALLED_DTE_OUT_OF_ORDER"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "CALL_FORWARDING_BY_THE_CALLED_DTE"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "CALL_FORWARDING_UNCONDITIONAL"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "RESERVED"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SsServiceType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CFU"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CF_BUSY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CF_NO_REPLY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "CF_NOT_REACHABLE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CF_ALL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CF_ALL_CONDITIONAL"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "CLIP"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "CLIR"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "COLP"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "COLR"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "WAIT"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "BAOC"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "BAOIC"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "BAOIC_EXC_HOME"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "BAIC"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "BAIC_ROAMING"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "ALL_BARRING"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "OUTGOING_BARRING"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "INCOMING_BARRING"
+        scalar_value: {
+            int32_t: 18
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SsRequestType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ACTIVATION"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DEACTIVATION"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "INTERROGATION"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "REGISTRATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ERASURE"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SsTeleserviceType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ALL_TELE_AND_BEARER_SERVICES"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ALL_TELESEVICES"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TELEPHONY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ALL_DATA_TELESERVICES"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SMS_SERVICES"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ALL_TELESERVICES_EXCEPT_SMS"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SuppServiceClass"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "VOICE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DATA"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FAX"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SMS"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "DATA_SYNC"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "DATA_ASYNC"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "PACKET"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "PAD"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 128
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioResponseInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioResponseType"
+    }
+    struct_value: {
+        name: "serial"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "error"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioError"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::AppStatus"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "appType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::AppType"
+    }
+    struct_value: {
+        name: "appState"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::AppState"
+    }
+    struct_value: {
+        name: "persoSubstate"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::PersoSubstate"
+    }
+    struct_value: {
+        name: "aidPtr"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "appLabelPtr"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "pin1Replaced"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "pin1"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::PinState"
+    }
+    struct_value: {
+        name: "pin2"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::PinState"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CardStatus"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cardState"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CardState"
+    }
+    struct_value: {
+        name: "universalPinState"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::PinState"
+    }
+    struct_value: {
+        name: "gsmUmtsSubscriptionAppIndex"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cdmaSubscriptionAppIndex"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "imsSubscriptionAppIndex"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "applications"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::AppStatus"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::UusInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "uusType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::UusType"
+    }
+    struct_value: {
+        name: "uusDcs"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::UusDcs"
+    }
+    struct_value: {
+        name: "uusData"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::Call"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "state"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CallState"
+    }
+    struct_value: {
+        name: "index"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "toa"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "isMpty"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "isMT"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "als"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "isVoice"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "isVoicePrivacy"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "number"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "numberPresentation"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CallPresentation"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "namePresentation"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CallPresentation"
+    }
+    struct_value: {
+        name: "uusInfo"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::UusInfo"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::Dial"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "address"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "clir"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::Clir"
+    }
+    struct_value: {
+        name: "uusInfo"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::UusInfo"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LastCallFailCauseInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "causeCode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::LastCallFailCause"
+    }
+    struct_value: {
+        name: "vendorCause"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::GsmSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "signalStrength"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "bitErrorRate"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "timingAdvance"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::WcdmaSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "signalStrength"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "bitErrorRate"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "dbm"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "ecio"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::EvdoSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "dbm"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "ecio"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "signalNoiseRatio"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LteSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "signalStrength"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "rsrp"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "rsrq"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "rssnr"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cqi"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "timingAdvance"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::TdScdmaSignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "rscp"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SignalStrength"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "gw"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::GsmSignalStrength"
+    }
+    struct_value: {
+        name: "cdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSignalStrength"
+    }
+    struct_value: {
+        name: "evdo"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::EvdoSignalStrength"
+    }
+    struct_value: {
+        name: "lte"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::LteSignalStrength"
+    }
+    struct_value: {
+        name: "tdScdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::TdScdmaSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SendSmsResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "messageRef"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "ackPDU"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "errorCode"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SetupDataCallResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "status"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "suggestedRetryTime"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "active"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "ifname"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "addresses"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "dnses"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "gateways"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "pcscf"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mtu"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::IccIo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "command"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "fileId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "path"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "p1"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "p2"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "p3"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "data"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "pin2"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "aid"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::IccIoResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sw1"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "sw2"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "simResponse"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::VoiceRegStateResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "regState"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RegState"
+    }
+    struct_value: {
+        name: "lac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "rat"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "baseStationId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "baseStationLatitude"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "baseStationLongitude"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cssSupported"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "systemId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "networkId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "roamingIndicator"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "systemIsInPrl"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "defaultRoamingIndicator"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "reasonForDenial"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "psc"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::DataRegStateResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "regState"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RegState"
+    }
+    struct_value: {
+        name: "lac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "rat"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "reasonDataDenied"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxDataCalls"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "tac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "phyCid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "eci"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "csgid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "tadv"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CallForwardInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CallForwardInfoStatus"
+    }
+    struct_value: {
+        name: "reason"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "serviceClass"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "toa"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "number"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "timeSeconds"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::OperatorInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "alphaLong"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "alphaShort"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "operatorNumeric"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::OperatorStatus"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SmsWriteArgs"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SmsWriteArgsStatus"
+    }
+    struct_value: {
+        name: "pdu"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "smsc"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsAddress"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "digitMode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsDigitMode"
+    }
+    struct_value: {
+        name: "numberMode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsNumberMode"
+    }
+    struct_value: {
+        name: "numberType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsNumberType"
+    }
+    struct_value: {
+        name: "numberPlan"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsNumberPlan"
+    }
+    struct_value: {
+        name: "digits"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsSubaddress"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "subaddressType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsSubaddressType"
+    }
+    struct_value: {
+        name: "odd"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "digits"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsMessage"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "teleserviceId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "isServicePresent"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "serviceCategory"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "address"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsAddress"
+    }
+    struct_value: {
+        name: "subAddress"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsSubaddress"
+    }
+    struct_value: {
+        name: "bearerData"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsAck"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "errorClass"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsErrorClass"
+    }
+    struct_value: {
+        name: "smsCauseCode"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaBroadcastSmsConfigInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "serviceCategory"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "language"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "selected"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSmsWriteArgs"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsWriteArgsStatus"
+    }
+    struct_value: {
+        name: "message"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSmsMessage"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::GsmBroadcastSmsConfigInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "fromServiceId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "toServiceId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "fromCodeScheme"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "toCodeScheme"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "selected"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellIdentityGsm"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mcc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mnc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "lac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "arfcn"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "bsic"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellIdentityWcdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mcc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mnc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "lac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "psc"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "uarfcn"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellIdentityCdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "networkId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "systemId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "basestationId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "longitude"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "latitude"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellIdentityLte"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mcc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mnc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "ci"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "pci"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "tac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "earfcn"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellIdentityTdscdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mcc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mnc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "lac"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cpid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoGsm"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellIdentityGsm"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CellIdentityGsm"
+    }
+    struct_value: {
+        name: "signalStrengthGsm"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::GsmSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoWcdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellIdentityWcdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CellIdentityWcdma"
+    }
+    struct_value: {
+        name: "signalStrengthWcdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::WcdmaSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoCdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellIdentityCdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CellIdentityCdma"
+    }
+    struct_value: {
+        name: "signalStrengthCdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSignalStrength"
+    }
+    struct_value: {
+        name: "signalStrengthEvdo"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::EvdoSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoLte"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellIdentityLte"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CellIdentityLte"
+    }
+    struct_value: {
+        name: "signalStrengthLte"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::LteSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfoTdscdma"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellIdentityTdscdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CellIdentityTdscdma"
+    }
+    struct_value: {
+        name: "signalStrengthTdscdma"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::TdScdmaSignalStrength"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CellInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cellInfoType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CellInfoType"
+    }
+    struct_value: {
+        name: "registered"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "timeStampType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::TimeStampType"
+    }
+    struct_value: {
+        name: "timeStamp"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "gsm"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CellInfoGsm"
+        }
+    }
+    struct_value: {
+        name: "cdma"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CellInfoCdma"
+        }
+    }
+    struct_value: {
+        name: "lte"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CellInfoLte"
+        }
+    }
+    struct_value: {
+        name: "wcdma"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CellInfoWcdma"
+        }
+    }
+    struct_value: {
+        name: "tdscdma"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CellInfoTdscdma"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::GsmSmsMessage"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "smscPdu"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "pdu"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::ImsSmsMessage"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "tech"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioTechnologyFamily"
+    }
+    struct_value: {
+        name: "retry"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "messageRef"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cdmaMessage"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSmsMessage"
+        }
+    }
+    struct_value: {
+        name: "gsmMessage"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::GsmSmsMessage"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SimApdu"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sessionId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "cla"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "instruction"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "p1"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "p2"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "p3"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "data"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::NvWriteItem"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "itemId"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::NvItem"
+    }
+    struct_value: {
+        name: "value"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SelectUiccSub"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "slot"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "appIndex"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "subType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SubscriptionType"
+    }
+    struct_value: {
+        name: "actStatus"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::UiccSubActStatus"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::HardwareConfigModem"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "rilModel"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "rat"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "maxVoice"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxData"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxStandby"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::HardwareConfigSim"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "modemUuid"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::HardwareConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::HardwareConfigType"
+    }
+    struct_value: {
+        name: "uuid"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "state"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::HardwareConfigState"
+    }
+    struct_value: {
+        name: "modem"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::HardwareConfigModem"
+        }
+    }
+    struct_value: {
+        name: "sim"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::HardwareConfigSim"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::DataProfileInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "profileId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "apn"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "protocol"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "authType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::ApnAuthType"
+    }
+    struct_value: {
+        name: "user"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "password"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::DataProfileInfoType"
+    }
+    struct_value: {
+        name: "maxConnsTime"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxConns"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "waitTime"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "enabled"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::RadioCapability"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "session"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "phase"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioCapabilityPhase"
+    }
+    struct_value: {
+        name: "raf"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioAccessFamily"
+    }
+    struct_value: {
+        name: "logicalModemUuid"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioCapabilityStatus"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LceStatusInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "lceStatus"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::LceStatus"
+    }
+    struct_value: {
+        name: "actualIntervalMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::LceDataInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "lastHopCapacityKbps"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "confidenceLevel"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "lceSuspended"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::ActivityStatsInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sleepModeTimeMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "idleModeTimeMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "txmModetimeMs"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 5
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+    struct_value: {
+        name: "rxModeTimeMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::Carrier"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mcc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "mnc"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "matchType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CarrierMatchType"
+    }
+    struct_value: {
+        name: "matchData"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CarrierRestrictions"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "allowedCarriers"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::Carrier"
+        }
+    }
+    struct_value: {
+        name: "excludedCarriers"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::Carrier"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SuppSvcNotification"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "isMT"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "code"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "index"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "number"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SimRefreshResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SimRefreshType"
+    }
+    struct_value: {
+        name: "efId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "aid"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaSignalInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "isPresent"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "signalType"
+        type: TYPE_SCALAR
+        scalar_type: "int8_t"
+    }
+    struct_value: {
+        name: "alertPitch"
+        type: TYPE_SCALAR
+        scalar_type: "int8_t"
+    }
+    struct_value: {
+        name: "signal"
+        type: TYPE_SCALAR
+        scalar_type: "int8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaCallWaiting"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "number"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "numberPresentation"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberPresentation"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "signalInfoRecord"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaSignalInfoRecord"
+    }
+    struct_value: {
+        name: "numbertype"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberType"
+    }
+    struct_value: {
+        name: "numberPlan"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaCallWaitingNumberPlan"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaDisplayInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "alphaBuf"
+        type: TYPE_STRING
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaNumberInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "number"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "numberType"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "numberPlan"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "pi"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "si"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaRedirectingNumberInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "redirectingNumber"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::radio::V1_0::CdmaNumberInfoRecord"
+    }
+    struct_value: {
+        name: "redirectingReason"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaRedirectingReason"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaLineControlInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "lineCtrlPolarityIncluded"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "lineCtrlToggle"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "lineCtrlReverse"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "lineCtrlPowerDenial"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaT53ClirInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cause"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaT53AudioControlInfoRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "upLink"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+    struct_value: {
+        name: "downLink"
+        type: TYPE_SCALAR
+        scalar_type: "uint8_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaInformationRecord"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::CdmaInfoRecName"
+    }
+    struct_value: {
+        name: "display"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaDisplayInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "number"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaNumberInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "signal"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaSignalInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "redir"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaRedirectingNumberInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "lineCtrl"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaLineControlInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "clir"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaT53ClirInfoRecord"
+        }
+    }
+    struct_value: {
+        name: "audioCtrl"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaT53AudioControlInfoRecord"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CdmaInformationRecords"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "infoRec"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CdmaInformationRecord"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::CfData"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cfInfo"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CallForwardInfo"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::SsInfoData"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "ssInfo"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::StkCcUnsolSsResult"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "serviceType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SsServiceType"
+    }
+    struct_value: {
+        name: "requestType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SsRequestType"
+    }
+    struct_value: {
+        name: "teleserviceType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SsTeleserviceType"
+    }
+    struct_value: {
+        name: "serviceClass"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::SuppServiceClass"
+    }
+    struct_value: {
+        name: "result"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::radio::V1_0::RadioError"
+    }
+    struct_value: {
+        name: "ssInfo"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::SsInfoData"
+        }
+    }
+    struct_value: {
+        name: "cfData"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::radio::V1_0::CfData"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::radio::V1_0::PcoDataInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "cid"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "bearerProto"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "pcoId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "contents"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
new file mode 100644
index 0000000..2995504
--- /dev/null
+++ b/sensors/1.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.sensors@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.cpp",
+        "android/hardware/sensors/1.0/SensorsAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.h",
+        "android/hardware/sensors/1.0/ISensors.h",
+        "android/hardware/sensors/1.0/IHwSensors.h",
+        "android/hardware/sensors/1.0/BnHwSensors.h",
+        "android/hardware/sensors/1.0/BpHwSensors.h",
+        "android/hardware/sensors/1.0/BsSensors.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.sensors@1.0",
+    generated_sources: ["android.hardware.sensors@1.0_genc++"],
+    generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.vts.cpp",
+        "android/hardware/sensors/1.0/Sensors.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/types.vts.h",
+        "android/hardware/sensors/1.0/Sensors.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.sensors.vts.driver@1.0",
+    generated_sources: ["android.hardware.sensors.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.sensors.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.sensors.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.sensors@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors@1.0-ISensors-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "ISensors.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/Sensors.vts.cpp",
+        "android/hardware/sensors/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.sensors@1.0-ISensors-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.sensors@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/sensors/1.0/ $(genDir)/android/hardware/sensors/1.0/",
+    srcs: [
+        "ISensors.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/sensors/1.0/Sensors.vts.h",
+        "android/hardware/sensors/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.sensors@1.0-ISensors-vts.profiler",
+    generated_sources: ["android.hardware.sensors@1.0-ISensors-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.sensors@1.0-ISensors-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.sensors@1.0-ISensors-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.sensors@1.0",
+    ],
+}
diff --git a/sensors/1.0/Android.mk b/sensors/1.0/Android.mk
new file mode 100644
index 0000000..5784916
--- /dev/null
+++ b/sensors/1.0/Android.mk
@@ -0,0 +1,40 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.sensors@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/sensors/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/ISensors.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.sensors@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/sensors/1.0/ISensors.hal b/sensors/1.0/ISensors.hal
new file mode 100644
index 0000000..5c8301a
--- /dev/null
+++ b/sensors/1.0/ISensors.hal
@@ -0,0 +1,195 @@
+/*
+ * 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.
+ */
+
+package android.hardware.sensors@1.0;
+
+interface ISensors {
+    /**
+     * Enumerate all available (static) sensors.
+     */
+    getSensorsList() generates (vec<SensorInfo> list);
+
+    /**
+     * Place the module in a specific mode. The following modes are defined
+     *
+     *  SENSOR_HAL_NORMAL_MODE - Normal operation. Default state of the module.
+     *
+     *  SENSOR_HAL_DATA_INJECTION_MODE - Loopback mode.
+     *    Data is injected for the supported sensors by the sensor service in
+     *    this mode.
+     *
+     * @return OK on success
+     *         BAD_VALUE if requested mode is not supported
+     *         PERMISSION_DENIED if operation is not allowed
+     */
+    setOperationMode(OperationMode mode) generates (Result result);
+
+    /* Activate/de-activate one sensor.
+     *
+     * After sensor de-activation, existing sensor events that have not
+     * been picked up by poll() must be abandoned immediately so that
+     * subsequent activation will not get stale sensor events (events
+     * that are generated prior to the latter activation).
+     *
+     * @param  sensorHandle is the handle of the sensor to change.
+     * @param  enabled set to true to enable, or false to disable the sensor.
+     *
+     * @return result OK on success, BAD_VALUE if sensorHandle is invalid.
+     */
+    activate(int32_t sensorHandle, bool enabled) generates (Result result);
+
+    /**
+     * Generate a vector of sensor events containing at most "maxCount"
+     * entries.
+     *
+     * Additionally a vector of SensorInfos is returned for any dynamic sensors
+     * connected as notified by returned events of type DYNAMIC_SENSOR_META.
+     *
+     * If there is no sensor event when this function is being called, block
+     * until there are sensor events available.
+     *
+     * @param  maxCount max number of samples can be returned, must be > 0.
+     *         Actual number of events returned in data must be <= maxCount
+     *         and > 0.
+     * @return result OK on success or BAD_VALUE if maxCount <= 0.
+     * @return data vector of Event contains sensor events.
+     * @return dynamicSensorsAdded vector of SensorInfo contains dynamic sensor
+     *         added. Each element corresponds to a dynamic sensor meta events
+     *         in data.
+     */
+    poll(int32_t maxCount)
+        generates (
+                Result result,
+                vec<Event> data,
+                vec<SensorInfo> dynamicSensorsAdded);
+
+    /*
+     * Sets a sensor’s parameters, including sampling frequency and maximum
+     * report latency. This function can be called while the sensor is
+     * activated, in which case it must not cause any sensor measurements to
+     * be lost: transitioning from one sampling rate to the other cannot cause
+     * lost events, nor can transitioning from a high maximum report latency to
+     * a low maximum report latency.
+     * See the Batching sensor results page for details:
+     * http://source.android.com/devices/sensors/batching.html
+     *
+     * @param  sensorHandle handle of sensor to be changed.
+     * @param  samplingPeriodNs specifies sensor sample period in nanoseconds.
+     * @param  maxReportLatencyNs allowed delay time before an event is sampled
+     *         to time of report.
+     * @return result OK on success, BAD_VALUE if any parameters are invalid.
+     */
+    batch(int32_t sensorHandle,
+          int64_t samplingPeriodNs,
+          int64_t maxReportLatencyNs) generates (Result result);
+
+    /*
+     * Trigger a flush of internal FIFO.
+     *
+     * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode"
+     * FIFO for the specified sensor and flushes the FIFO.  If the FIFO is empty
+     * or if the sensor doesn't support batching (FIFO size zero), return
+     * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream.
+     * This applies to all sensors other than one-shot sensors. If the sensor
+     * is a one-shot sensor, flush must return BAD_VALUE and not generate any
+     * flush complete metadata.  If the sensor is not active at the time flush()
+     * is called, flush() return BAD_VALUE.
+     *
+     * @param   sensorHandle handle of sensor to be flushed.
+     * @return  result OK on success and BAD_VALUE if sensorHandle is invalid.
+     */
+    flush(int32_t sensorHandle) generates (Result result);
+
+    /*
+     * Inject a single sensor event or push operation environment parameters to
+     * device.
+     *
+     * When device is in NORMAL mode, this function is called to push operation
+     * environment data to device. In this operation, Event is always of
+     * SensorType::AdditionalInfo type. See operation evironment parameters
+     * section in AdditionalInfoType.
+     *
+     * When device is in DATA_INJECTION mode, this function is also used for
+     * injecting sensor events.
+     *
+     * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO
+     * type events should not be routed back to poll() function.
+     *
+     * @see AdditionalInfoType
+     * @see OperationMode
+     * @param   event sensor event to be injected
+     * @return  result OK on success; PERMISSION_DENIED if operation is not
+     *          allowed; INVALID_OPERATION, if this functionality is
+     *          unsupported; BAD_VALUE if sensor event cannot be injected.
+     */
+    injectSensorData(Event event) generates (Result result);
+
+    /*
+     * Register direct report channel.
+     *
+     * Register a direct channel with supplied shared memory information. Upon
+     * return, the sensor hardware is responsible for resetting the memory
+     * content to initial value (depending on memory format settings).
+     *
+     * @param   mem shared memory info data structure.
+     * @return  result OK on success; BAD_VALUE if shared memory information is
+     *          not consistent; NO_MEMORY if shared memory cannot be used by
+     *          sensor system; INVALID_OPERATION if functionality is not
+     *          supported.
+     * @return  channelHandle a positive integer used for referencing registered
+     *          direct channel (>0) in configureDirectReport and
+     *          unregisterDirectChannel if result is OK, -1 otherwise.
+     */
+    registerDirectChannel(SharedMemInfo mem)
+            generates (Result result, int32_t channelHandle);
+
+    /*
+     * Unregister direct report channel.
+     *
+     * Unregister a direct channel previously registered using
+     * registerDirectChannel, and remove all active sensor report configured in
+     * still active sensor report configured in the direct channel.
+     *
+     * @param   channelHandle handle of direct channel to be unregistered.
+     * @return  result OK if direct report is supported; INVALID_OPERATION
+     *          otherwise.
+     */
+    unregisterDirectChannel(int32_t channelHandle) generates (Result result);
+
+    /*
+     * Configure direct sensor event report in direct channel.
+     *
+     * This function start, modify rate or stop direct report of a sensor in a
+     * certain direct channel.
+     *
+     * @param   sensorHandle handle of sensor to be configured. When combined
+     *          with STOP rate, sensorHandle can be -1 to denote all active
+     *          sensors in the direct channel specified by channel Handle.
+     * @param   channelHandle handle of direct channel to be configured.
+     * @param   rate rate level, see RateLevel enum.
+     *
+     * @return  result OK on success; BAD_VALUE if parameter is invalid (such as
+     *          rate level is not supported by sensor, channelHandle does not
+     *          exist, etc); INVALID_OPERATION if functionality is not
+     *          supported.
+     * @return  reportToken positive integer to identify multiple sensors of
+     *          the same type in a single direct channel. Ignored if rate is
+     *          STOP. See SharedMemFormat.
+     */
+    configDirectReport(
+            int32_t sensorHandle, int32_t channelHandle, RateLevel rate)
+            generates (Result result, int32_t reportToken);
+};
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
new file mode 100644
index 0000000..994febe
--- /dev/null
+++ b/sensors/1.0/default/Android.bp
@@ -0,0 +1,41 @@
+cc_library_shared {
+    name: "android.hardware.sensors@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Sensors.cpp"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.sensors@1.0",
+    ],
+    static_libs: [
+        "android.hardware.sensors@1.0-convert",
+        "multihal",
+    ],
+    local_include_dirs: ["include/sensors"],
+}
+
+cc_library_static {
+    name: "android.hardware.sensors@1.0-convert",
+    srcs: ["convert.cpp"],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.sensors@1.0",
+    ],
+    local_include_dirs: ["include/sensors"],
+}
+
+
diff --git a/sensors/1.0/default/Android.mk b/sensors/1.0/default/Android.mk
new file mode 100644
index 0000000..f37c3cb
--- /dev/null
+++ b/sensors/1.0/default/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.sensors@1.0-service
+LOCAL_INIT_RC := android.hardware.sensors@1.0-service.rc
+LOCAL_SRC_FILES := \
+        service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+        liblog \
+        libcutils \
+        libdl \
+        libbase \
+        libutils \
+        libhardware_legacy \
+        libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+        libhwbinder \
+        libhidlbase \
+        libhidltransport \
+        android.hardware.sensors@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/sensors/1.0/default/Sensors.cpp b/sensors/1.0/default/Sensors.cpp
new file mode 100644
index 0000000..41eb945
--- /dev/null
+++ b/sensors/1.0/default/Sensors.cpp
@@ -0,0 +1,326 @@
+/*
+ * 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.
+ */
+
+#include "Sensors.h"
+#include "convert.h"
+#include "multihal.h"
+
+#include <android-base/logging.h>
+
+#include <sys/stat.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * If a multi-hal configuration file exists in the proper location,
+ * return true indicating we need to use multi-hal functionality.
+ */
+static bool UseMultiHal() {
+    const std::string& name = MULTI_HAL_CONFIG_FILE_PATH;
+    struct stat buffer;
+    return (stat (name.c_str(), &buffer) == 0);
+}
+
+static Result ResultFromStatus(status_t err) {
+    switch (err) {
+        case OK:
+            return Result::OK;
+        case PERMISSION_DENIED:
+            return Result::PERMISSION_DENIED;
+        case NO_MEMORY:
+            return Result::NO_MEMORY;
+        case BAD_VALUE:
+            return Result::BAD_VALUE;
+        default:
+            return Result::INVALID_OPERATION;
+    }
+}
+
+Sensors::Sensors()
+    : mInitCheck(NO_INIT),
+      mSensorModule(nullptr),
+      mSensorDevice(nullptr) {
+    status_t err = OK;
+    if (UseMultiHal()) {
+        mSensorModule = ::get_multi_hal_module_info();
+    } else {
+        err = hw_get_module(
+            SENSORS_HARDWARE_MODULE_ID,
+            (hw_module_t const **)&mSensorModule);
+    }
+    if (mSensorModule == NULL) {
+        err = UNKNOWN_ERROR;
+    }
+
+    if (err != OK) {
+        LOG(ERROR) << "Couldn't load "
+                   << SENSORS_HARDWARE_MODULE_ID
+                   << " module ("
+                   << strerror(-err)
+                   << ")";
+
+        mInitCheck = err;
+        return;
+    }
+
+    err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
+
+    if (err != OK) {
+        LOG(ERROR) << "Couldn't open device for module "
+                   << SENSORS_HARDWARE_MODULE_ID
+                   << " ("
+                   << strerror(-err)
+                   << ")";
+
+        mInitCheck = err;
+        return;
+    }
+
+    // Require all the old HAL APIs to be present except for injection, which
+    // is considered optional.
+    CHECK_GE(getHalDeviceVersion(), SENSORS_DEVICE_API_VERSION_1_3);
+
+    mInitCheck = OK;
+}
+
+status_t Sensors::initCheck() const {
+    return mInitCheck;
+}
+
+Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
+    sensor_t const *list;
+    size_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
+
+    hidl_vec<SensorInfo> out;
+    out.resize(count);
+
+    for (size_t i = 0; i < count; ++i) {
+        const sensor_t *src = &list[i];
+        SensorInfo *dst = &out[i];
+
+        convertFromSensor(*src, dst);
+    }
+
+    _hidl_cb(out);
+
+    return Void();
+}
+
+int Sensors::getHalDeviceVersion() const {
+    if (!mSensorDevice) {
+        return -1;
+    }
+
+    return mSensorDevice->common.version;
+}
+
+Return<Result> Sensors::setOperationMode(OperationMode mode) {
+    return ResultFromStatus(mSensorModule->set_operation_mode((uint32_t)mode));
+}
+
+Return<Result> Sensors::activate(
+        int32_t sensor_handle, bool enabled) {
+    return ResultFromStatus(
+            mSensorDevice->activate(
+                reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
+                sensor_handle,
+                enabled));
+}
+
+Return<void> Sensors::poll(int32_t maxCount, poll_cb _hidl_cb) {
+    hidl_vec<Event> out;
+    hidl_vec<SensorInfo> dynamicSensorsAdded;
+
+    if (maxCount <= 0) {
+        _hidl_cb(Result::BAD_VALUE, out, dynamicSensorsAdded);
+        return Void();
+    }
+
+    int bufferSize = maxCount <= kPollMaxBufferSize ? maxCount : kPollMaxBufferSize;
+
+    std::unique_ptr<sensors_event_t[]> data(new sensors_event_t[bufferSize]);
+
+    int err = mSensorDevice->poll(
+            reinterpret_cast<sensors_poll_device_t *>(mSensorDevice),
+            data.get(), bufferSize);
+
+    if (err < 0) {
+        _hidl_cb(ResultFromStatus(err), out, dynamicSensorsAdded);
+        return Void();
+    }
+
+    const size_t count = (size_t)err;
+
+    for (size_t i = 0; i < count; ++i) {
+        if (data[i].type != SENSOR_TYPE_DYNAMIC_SENSOR_META) {
+            continue;
+        }
+
+        const dynamic_sensor_meta_event_t *dyn = &data[i].dynamic_sensor_meta;
+
+        if (!dyn->connected) {
+            continue;
+        }
+
+        CHECK(dyn->sensor != nullptr);
+        CHECK_EQ(dyn->sensor->handle, dyn->handle);
+
+        SensorInfo info;
+        convertFromSensor(*dyn->sensor, &info);
+
+        size_t numDynamicSensors = dynamicSensorsAdded.size();
+        dynamicSensorsAdded.resize(numDynamicSensors + 1);
+        dynamicSensorsAdded[numDynamicSensors] = info;
+    }
+
+    out.resize(count);
+    convertFromSensorEvents(err, data.get(), &out);
+
+    _hidl_cb(Result::OK, out, dynamicSensorsAdded);
+
+    return Void();
+}
+
+Return<Result> Sensors::batch(
+        int32_t sensor_handle,
+        int64_t sampling_period_ns,
+        int64_t max_report_latency_ns) {
+    return ResultFromStatus(
+            mSensorDevice->batch(
+                mSensorDevice,
+                sensor_handle,
+                0, /*flags*/
+                sampling_period_ns,
+                max_report_latency_ns));
+}
+
+Return<Result> Sensors::flush(int32_t sensor_handle) {
+    return ResultFromStatus(mSensorDevice->flush(mSensorDevice, sensor_handle));
+}
+
+Return<Result> Sensors::injectSensorData(const Event& event) {
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+        return Result::INVALID_OPERATION;
+    }
+
+    sensors_event_t out;
+    convertToSensorEvent(event, &out);
+
+    return ResultFromStatus(
+            mSensorDevice->inject_sensor_data(mSensorDevice, &out));
+}
+
+Return<void> Sensors::registerDirectChannel(
+        const SharedMemInfo& mem, registerDirectChannel_cb _hidl_cb) {
+    if (mSensorDevice->register_direct_channel == nullptr
+            || mSensorDevice->config_direct_report == nullptr) {
+        // HAL does not support
+        _hidl_cb(Result::INVALID_OPERATION, -1);
+        return Void();
+    }
+
+    sensors_direct_mem_t m;
+    if (!convertFromSharedMemInfo(mem, &m)) {
+      _hidl_cb(Result::BAD_VALUE, -1);
+      return Void();
+    }
+
+    int err = mSensorDevice->register_direct_channel(mSensorDevice, &m, -1);
+
+    if (err < 0) {
+        _hidl_cb(ResultFromStatus(err), -1);
+    } else {
+        int32_t channelHandle = static_cast<int32_t>(err);
+        _hidl_cb(Result::OK, channelHandle);
+    }
+    return Void();
+}
+
+Return<Result> Sensors::unregisterDirectChannel(int32_t channelHandle) {
+    if (mSensorDevice->register_direct_channel == nullptr
+            || mSensorDevice->config_direct_report == nullptr) {
+        // HAL does not support
+        return Result::INVALID_OPERATION;
+    }
+
+    mSensorDevice->register_direct_channel(mSensorDevice, nullptr, channelHandle);
+
+    return Result::OK;
+}
+
+Return<void> Sensors::configDirectReport(
+        int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+        configDirectReport_cb _hidl_cb) {
+    if (mSensorDevice->register_direct_channel == nullptr
+            || mSensorDevice->config_direct_report == nullptr) {
+        // HAL does not support
+        _hidl_cb(Result::INVALID_OPERATION, -1);
+        return Void();
+    }
+
+    sensors_direct_cfg_t cfg = {
+        .rate_level = convertFromRateLevel(rate)
+    };
+    if (cfg.rate_level < 0) {
+        _hidl_cb(Result::BAD_VALUE, -1);
+        return Void();
+    }
+
+    int err = mSensorDevice->config_direct_report(mSensorDevice,
+            sensorHandle, channelHandle, &cfg);
+
+    if (rate == RateLevel::STOP) {
+        _hidl_cb(ResultFromStatus(err), -1);
+    } else {
+        _hidl_cb(err > 0 ? Result::OK : ResultFromStatus(err), err);
+    }
+    return Void();
+}
+
+// static
+void Sensors::convertFromSensorEvents(
+        size_t count,
+        const sensors_event_t *srcArray,
+        hidl_vec<Event> *dstVec) {
+    for (size_t i = 0; i < count; ++i) {
+        const sensors_event_t &src = srcArray[i];
+        Event *dst = &(*dstVec)[i];
+
+        convertFromSensorEvent(src, dst);
+    }
+}
+
+ISensors *HIDL_FETCH_ISensors(const char * /* hal */) {
+    Sensors *sensors = new Sensors;
+    if (sensors->initCheck() != OK) {
+        delete sensors;
+        sensors = nullptr;
+
+        return nullptr;
+    }
+
+    return sensors;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
diff --git a/sensors/1.0/default/Sensors.h b/sensors/1.0/default/Sensors.h
new file mode 100644
index 0000000..09729d3
--- /dev/null
+++ b/sensors/1.0/default/Sensors.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_SENSORS_H_
+
+#define HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_SENSORS_H_
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <hardware/sensors.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V1_0 {
+namespace implementation {
+
+
+struct Sensors : public ::android::hardware::sensors::V1_0::ISensors {
+    Sensors();
+
+    status_t initCheck() const;
+
+    Return<void> getSensorsList(getSensorsList_cb _hidl_cb) override;
+
+    Return<Result> setOperationMode(OperationMode mode) override;
+
+    Return<Result> activate(
+            int32_t sensor_handle, bool enabled) override;
+
+    Return<void> poll(int32_t maxCount, poll_cb _hidl_cb) override;
+
+    Return<Result> batch(
+            int32_t sensor_handle,
+            int64_t sampling_period_ns,
+            int64_t max_report_latency_ns) override;
+
+    Return<Result> flush(int32_t sensor_handle) override;
+
+    Return<Result> injectSensorData(const Event& event) override;
+
+    Return<void> registerDirectChannel(
+            const SharedMemInfo& mem, registerDirectChannel_cb _hidl_cb) override;
+
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override;
+
+    Return<void> configDirectReport(
+            int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+            configDirectReport_cb _hidl_cb) override;
+
+private:
+    static constexpr int32_t kPollMaxBufferSize = 128;
+    status_t mInitCheck;
+    sensors_module_t *mSensorModule;
+    sensors_poll_device_1_t *mSensorDevice;
+
+    int getHalDeviceVersion() const;
+
+    static void convertFromSensorEvents(
+            size_t count, const sensors_event_t *src, hidl_vec<Event> *dst);
+
+    DISALLOW_COPY_AND_ASSIGN(Sensors);
+};
+
+extern "C" ISensors *HIDL_FETCH_ISensors(const char *name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_SENSORS_H_
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
new file mode 100644
index 0000000..2cba0fc
--- /dev/null
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -0,0 +1,4 @@
+service sensors-hal-1-0 /system/bin/hw/android.hardware.sensors@1.0-service
+    class main
+    user system
+    group system readproc
diff --git a/sensors/1.0/default/convert.cpp b/sensors/1.0/default/convert.cpp
new file mode 100644
index 0000000..acff6ca
--- /dev/null
+++ b/sensors/1.0/default/convert.cpp
@@ -0,0 +1,392 @@
+/*
+ * 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.
+ */
+
+#include "convert.h"
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V1_0 {
+namespace implementation {
+
+void convertFromSensor(const sensor_t &src, SensorInfo *dst) {
+    dst->name = src.name;
+    dst->vendor = src.vendor;
+    dst->version = src.version;
+    dst->sensorHandle = src.handle;
+    dst->type = (SensorType)src.type;
+    dst->maxRange = src.maxRange;
+    dst->resolution = src.resolution;
+    dst->power = src.power;
+    dst->minDelay = src.minDelay;
+    dst->fifoReservedEventCount = src.fifoReservedEventCount;
+    dst->fifoMaxEventCount = src.fifoMaxEventCount;
+    dst->typeAsString = src.stringType;
+    dst->requiredPermission = src.requiredPermission;
+    dst->maxDelay = src.maxDelay;
+    dst->flags = src.flags;
+}
+
+void convertToSensor(
+        const ::android::hardware::sensors::V1_0::SensorInfo &src,
+        sensor_t *dst) {
+    dst->name = strdup(src.name.c_str());
+    dst->vendor = strdup(src.vendor.c_str());
+    dst->version = src.version;
+    dst->handle = src.sensorHandle;
+    dst->type = (int)src.type;
+    dst->maxRange = src.maxRange;
+    dst->resolution = src.resolution;
+    dst->power = src.power;
+    dst->minDelay = src.minDelay;
+    dst->fifoReservedEventCount = src.fifoReservedEventCount;
+    dst->fifoMaxEventCount = src.fifoMaxEventCount;
+    dst->stringType = strdup(src.typeAsString.c_str());
+    dst->requiredPermission = strdup(src.requiredPermission.c_str());
+    dst->maxDelay = src.maxDelay;
+    dst->flags = src.flags;
+    dst->reserved[0] = dst->reserved[1] = 0;
+}
+
+void convertFromSensorEvent(const sensors_event_t &src, Event *dst) {
+    typedef ::android::hardware::sensors::V1_0::SensorType SensorType;
+    typedef ::android::hardware::sensors::V1_0::MetaDataEventType MetaDataEventType;
+
+    dst->sensorHandle = src.sensor;
+    dst->sensorType = (SensorType)src.type;
+    dst->timestamp = src.timestamp;
+
+    switch (dst->sensorType) {
+        case SensorType::META_DATA:
+        {
+            dst->u.meta.what = (MetaDataEventType)src.meta_data.what;
+            break;
+        }
+
+        case SensorType::ACCELEROMETER:
+        case SensorType::MAGNETIC_FIELD:
+        case SensorType::ORIENTATION:
+        case SensorType::GYROSCOPE:
+        case SensorType::GRAVITY:
+        case SensorType::LINEAR_ACCELERATION:
+        {
+            dst->u.vec3.x = src.acceleration.x;
+            dst->u.vec3.y = src.acceleration.y;
+            dst->u.vec3.z = src.acceleration.z;
+            dst->u.vec3.status = (SensorStatus)src.acceleration.status;
+            break;
+        }
+
+        case SensorType::ROTATION_VECTOR:
+        case SensorType::GAME_ROTATION_VECTOR:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+        {
+            dst->u.vec4.x = src.data[0];
+            dst->u.vec4.y = src.data[1];
+            dst->u.vec4.z = src.data[2];
+            dst->u.vec4.w = src.data[3];
+            break;
+        }
+
+      case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+      case SensorType::GYROSCOPE_UNCALIBRATED:
+      case SensorType::ACCELEROMETER_UNCALIBRATED:
+      {
+          dst->u.uncal.x = src.uncalibrated_gyro.x_uncalib;
+          dst->u.uncal.y = src.uncalibrated_gyro.y_uncalib;
+          dst->u.uncal.z = src.uncalibrated_gyro.z_uncalib;
+          dst->u.uncal.x_bias = src.uncalibrated_gyro.x_bias;
+          dst->u.uncal.y_bias = src.uncalibrated_gyro.y_bias;
+          dst->u.uncal.z_bias = src.uncalibrated_gyro.z_bias;
+          break;
+      }
+
+      case SensorType::DEVICE_ORIENTATION:
+      case SensorType::LIGHT:
+      case SensorType::PRESSURE:
+      case SensorType::TEMPERATURE:
+      case SensorType::PROXIMITY:
+      case SensorType::RELATIVE_HUMIDITY:
+      case SensorType::AMBIENT_TEMPERATURE:
+      case SensorType::SIGNIFICANT_MOTION:
+      case SensorType::STEP_DETECTOR:
+      case SensorType::TILT_DETECTOR:
+      case SensorType::WAKE_GESTURE:
+      case SensorType::GLANCE_GESTURE:
+      case SensorType::PICK_UP_GESTURE:
+      case SensorType::WRIST_TILT_GESTURE:
+      case SensorType::STATIONARY_DETECT:
+      case SensorType::MOTION_DETECT:
+      case SensorType::HEART_BEAT:
+      {
+          dst->u.scalar = src.data[0];
+          break;
+      }
+
+      case SensorType::STEP_COUNTER:
+      {
+          dst->u.stepCount = src.u64.step_counter;
+          break;
+      }
+
+      case SensorType::HEART_RATE:
+      {
+          dst->u.heartRate.bpm = src.heart_rate.bpm;
+          dst->u.heartRate.status = (SensorStatus)src.heart_rate.status;
+          break;
+      }
+
+      case SensorType::POSE_6DOF:  // 15 floats
+      {
+          for (size_t i = 0; i < 15; ++i) {
+              dst->u.pose6DOF[i] = src.data[i];
+          }
+          break;
+      }
+
+      case SensorType::DYNAMIC_SENSOR_META:
+      {
+          dst->u.dynamic.connected = src.dynamic_sensor_meta.connected;
+          dst->u.dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
+
+          memcpy(dst->u.dynamic.uuid.data(),
+                 src.dynamic_sensor_meta.uuid,
+                 16);
+
+          break;
+      }
+
+      case SensorType::ADDITIONAL_INFO:
+      {
+          ::android::hardware::sensors::V1_0::AdditionalInfo *dstInfo =
+              &dst->u.additional;
+
+          const additional_info_event_t &srcInfo = src.additional_info;
+
+          dstInfo->type =
+              (::android::hardware::sensors::V1_0::AdditionalInfoType)
+                  srcInfo.type;
+
+          dstInfo->serial = srcInfo.serial;
+
+          CHECK_EQ(sizeof(dstInfo->u), sizeof(srcInfo.data_int32));
+          memcpy(&dstInfo->u, srcInfo.data_int32, sizeof(srcInfo.data_int32));
+          break;
+      }
+
+      default:
+      {
+          CHECK_GE((int32_t)dst->sensorType,
+                   (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+
+          memcpy(dst->u.data.data(), src.data, 16 * sizeof(float));
+          break;
+      }
+  }
+}
+
+void convertToSensorEvent(const Event &src, sensors_event_t *dst) {
+  dst->version = sizeof(sensors_event_t);
+  dst->sensor = src.sensorHandle;
+  dst->type = (int32_t)src.sensorType;
+  dst->reserved0 = 0;
+  dst->timestamp = src.timestamp;
+  dst->flags = 0;
+  dst->reserved1[0] = dst->reserved1[1] = dst->reserved1[2] = 0;
+
+  switch (src.sensorType) {
+      case SensorType::META_DATA:
+      {
+          dst->meta_data.what = (int32_t)src.u.meta.what;
+          dst->meta_data.sensor = dst->sensor;
+          break;
+      }
+
+      case SensorType::ACCELEROMETER:
+      case SensorType::MAGNETIC_FIELD:
+      case SensorType::ORIENTATION:
+      case SensorType::GYROSCOPE:
+      case SensorType::GRAVITY:
+      case SensorType::LINEAR_ACCELERATION:
+      {
+          dst->acceleration.x = src.u.vec3.x;
+          dst->acceleration.y = src.u.vec3.y;
+          dst->acceleration.z = src.u.vec3.z;
+          dst->acceleration.status = (int8_t)src.u.vec3.status;
+          break;
+      }
+
+      case SensorType::ROTATION_VECTOR:
+      case SensorType::GAME_ROTATION_VECTOR:
+      case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+      {
+          dst->data[0] = src.u.vec4.x;
+          dst->data[1] = src.u.vec4.y;
+          dst->data[2] = src.u.vec4.z;
+          dst->data[3] = src.u.vec4.w;
+          break;
+      }
+
+      case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case SensorType::GYROSCOPE_UNCALIBRATED:
+        case SensorType::ACCELEROMETER_UNCALIBRATED:
+        {
+            dst->uncalibrated_gyro.x_uncalib = src.u.uncal.x;
+            dst->uncalibrated_gyro.y_uncalib = src.u.uncal.y;
+            dst->uncalibrated_gyro.z_uncalib = src.u.uncal.z;
+            dst->uncalibrated_gyro.x_bias = src.u.uncal.x_bias;
+            dst->uncalibrated_gyro.y_bias = src.u.uncal.y_bias;
+            dst->uncalibrated_gyro.z_bias = src.u.uncal.z_bias;
+            break;
+        }
+
+        case SensorType::DEVICE_ORIENTATION:
+        case SensorType::LIGHT:
+        case SensorType::PRESSURE:
+        case SensorType::TEMPERATURE:
+        case SensorType::PROXIMITY:
+        case SensorType::RELATIVE_HUMIDITY:
+        case SensorType::AMBIENT_TEMPERATURE:
+        case SensorType::SIGNIFICANT_MOTION:
+        case SensorType::STEP_DETECTOR:
+        case SensorType::TILT_DETECTOR:
+        case SensorType::WAKE_GESTURE:
+        case SensorType::GLANCE_GESTURE:
+        case SensorType::PICK_UP_GESTURE:
+        case SensorType::WRIST_TILT_GESTURE:
+        case SensorType::STATIONARY_DETECT:
+        case SensorType::MOTION_DETECT:
+        case SensorType::HEART_BEAT:
+        {
+            dst->data[0] = src.u.scalar;
+            break;
+        }
+
+        case SensorType::STEP_COUNTER:
+        {
+            dst->u64.step_counter = src.u.stepCount;
+            break;
+        }
+
+        case SensorType::HEART_RATE:
+        {
+            dst->heart_rate.bpm = src.u.heartRate.bpm;
+            dst->heart_rate.status = (int8_t)src.u.heartRate.status;
+            break;
+        }
+
+        case SensorType::POSE_6DOF:  // 15 floats
+        {
+            for (size_t i = 0; i < 15; ++i) {
+                dst->data[i] = src.u.pose6DOF[i];
+            }
+            break;
+        }
+
+        case SensorType::DYNAMIC_SENSOR_META:
+        {
+            dst->dynamic_sensor_meta.connected = src.u.dynamic.connected;
+            dst->dynamic_sensor_meta.handle = src.u.dynamic.sensorHandle;
+            dst->dynamic_sensor_meta.sensor = NULL;  // to be filled in later
+
+            memcpy(dst->dynamic_sensor_meta.uuid,
+                   src.u.dynamic.uuid.data(),
+                   16);
+
+            break;
+        }
+
+        case SensorType::ADDITIONAL_INFO:
+        {
+            const ::android::hardware::sensors::V1_0::AdditionalInfo &srcInfo =
+                src.u.additional;
+
+            additional_info_event_t *dstInfo = &dst->additional_info;
+            dstInfo->type = (int32_t)srcInfo.type;
+            dstInfo->serial = srcInfo.serial;
+
+            CHECK_EQ(sizeof(srcInfo.u), sizeof(dstInfo->data_int32));
+
+            memcpy(dstInfo->data_int32,
+                   &srcInfo.u,
+                   sizeof(dstInfo->data_int32));
+
+            break;
+        }
+
+        default:
+        {
+            CHECK_GE((int32_t)src.sensorType,
+                     (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+
+            memcpy(dst->data, src.u.data.data(), 16 * sizeof(float));
+            break;
+        }
+    }
+}
+
+bool convertFromSharedMemInfo(const SharedMemInfo& memIn, sensors_direct_mem_t *memOut) {
+    if (memOut == nullptr) {
+        return false;
+    }
+
+    switch(memIn.type) {
+        case SharedMemType::ASHMEM:
+            memOut->type = SENSOR_DIRECT_MEM_TYPE_ASHMEM;
+            break;
+        case SharedMemType::GRALLOC:
+            memOut->type = SENSOR_DIRECT_MEM_TYPE_GRALLOC;
+            break;
+        default:
+            return false;
+    }
+
+    switch(memIn.format) {
+        case SharedMemFormat::SENSORS_EVENT:
+            memOut->format = SENSOR_DIRECT_FMT_SENSORS_EVENT;
+            break;
+        default:
+            return false;
+    }
+
+    memOut->size = memIn.size;
+    memOut->handle = memIn.memoryHandle;
+    return true;
+}
+
+int convertFromRateLevel(RateLevel rate) {
+    switch(rate) {
+        case RateLevel::STOP:
+            return SENSOR_DIRECT_RATE_STOP;
+        case RateLevel::NORMAL:
+            return SENSOR_DIRECT_RATE_NORMAL;
+        case RateLevel::FAST:
+            return SENSOR_DIRECT_RATE_FAST;
+        case RateLevel::VERY_FAST:
+            return SENSOR_DIRECT_RATE_VERY_FAST;
+        default:
+            return -1;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
+
diff --git a/sensors/1.0/default/include/sensors/convert.h b/sensors/1.0/default/include/sensors/convert.h
new file mode 100644
index 0000000..c3a0125
--- /dev/null
+++ b/sensors/1.0/default/include/sensors/convert.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_INCLUDE_CONVERT_H_
+
+#define HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_INCLUDE_CONVERT_H_
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <hardware/sensors.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace V1_0 {
+namespace implementation {
+
+void convertFromSensor(const sensor_t &src, SensorInfo *dst);
+void convertToSensor(const SensorInfo &src, sensor_t *dst);
+
+void convertFromSensorEvent(const sensors_event_t &src, Event *dst);
+void convertToSensorEvent(const Event &src, sensors_event_t *dst);
+
+bool convertFromSharedMemInfo(const SharedMemInfo& memIn, sensors_direct_mem_t *memOut);
+int convertFromRateLevel(RateLevel rate);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace sensors
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_SENSORS_V1_0_DEFAULT_INCLUDE_CONVERT_H_
diff --git a/sensors/1.0/default/service.cpp b/sensors/1.0/default/service.cpp
new file mode 100644
index 0000000..5bcfe4b
--- /dev/null
+++ b/sensors/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.sensors@1.0-service"
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::sensors::V1_0::ISensors;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<ISensors>();
+}
diff --git a/sensors/1.0/types.hal b/sensors/1.0/types.hal
new file mode 100644
index 0000000..c0d8c5d
--- /dev/null
+++ b/sensors/1.0/types.hal
@@ -0,0 +1,1263 @@
+/*
+ * 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.
+ */
+
+package android.hardware.sensors@1.0;
+
+/**
+ * Please see the Sensors section of source.android.com for an
+ * introduction to and detailed descriptions of Android sensor types:
+ * http://source.android.com/devices/sensors/index.html
+ */
+
+/* Type enumerating various result codes returned from ISensors methods */
+enum Result : int32_t {
+    OK,
+    PERMISSION_DENIED                   = -1,
+    NO_MEMORY                           = -12,
+    BAD_VALUE                           = -22,
+    INVALID_OPERATION                   = -38,
+};
+
+/*
+ * Sensor HAL modes used in setOperationMode method
+ */
+@export(name="", value_prefix="SENSOR_HAL_", value_suffix="_MODE")
+enum OperationMode : int32_t {
+    NORMAL                          = 0,
+    DATA_INJECTION                  = 1,
+};
+
+/*
+ * Sensor type
+ *
+ * Each sensor has a type which defines what this sensor measures and how
+ * measures are reported. See the Base sensors and Composite sensors lists
+ * for complete descriptions:
+ * http://source.android.com/devices/sensors/base_triggers.html
+ * http://source.android.com/devices/sensors/composite_sensors.html
+ *
+ * Device manufacturers (OEMs) can define their own sensor types, for
+ * their private use by applications or services provided by them. Such
+ * sensor types are specific to an OEM and can't be exposed in the SDK.
+ * These types must start at SensorType::DEVICE_PRIVATE_BASE.
+ *
+ * All sensors defined outside of the device private range must correspond to
+ * a type defined in this file, and must satisfy the characteristics listed in
+ * the description of the sensor type.
+ *
+ * Each sensor also has a "typeAsString".
+ *  - string type of sensors defined in this file is overridden by Android to
+ *    values defined in Android API with "android.sensor." prefix.
+ *    Example: for an accelerometer,
+ *      type = SensorType::Acclerometer
+ *      typeAsString = "" (will be replace by "android.sensor.accelerometer" by
+ *                         Android frameowrk)
+ *  - string type of sensors inside of the device private range MUST be prefixed
+ *    by the sensor provider's or OEM reverse domain name. In particular, they
+ *    cannot use the "android.sensor." prefix.
+ *
+ * When android introduces a new sensor type that can replace an OEM-defined
+ * sensor type, the OEM must use the official sensor type and stringType on
+ * versions of the HAL that support this new official sensor type.
+ *
+ * Example (made up): Suppose Google's Glass team wants to surface a sensor
+ * detecting that Glass is on a head.
+ *  - Such a sensor is not officially supported in android KitKat
+ *  - Glass devices launching on KitKat can implement a sensor with
+ *      type = 0x10001
+ *      typeAsString = "com.google.glass.onheaddetector"
+ *  - In L android release, if android decides to define
+ *    SensorType::ON_HEAD_DETECTOR and STRING_SensorType::ON_HEAD_DETECTOR,
+ *    those types should replace the Glass-team-specific types in all future
+ *    launches.
+ *  - When launching Glass on the L release, Google should now use the official
+ *    type (SensorType::ON_HEAD_DETECTOR) and stringType.
+ *  - This way, all applications can now use this sensor.
+ */
+
+/*
+ * Wake up sensors.
+ * Each sensor may have either or both a wake-up and a non-wake variant.
+ * When registered in batch mode, wake-up sensors will wake up the AP when
+ * their FIFOs are full or when the batch timeout expires. A separate FIFO has
+ * to be maintained for wake up sensors and non wake up sensors. The non
+ * wake-up sensors need to overwrite their FIFOs when they are full till the AP
+ * wakes up and the wake-up sensors will wake-up the AP when their FIFOs are
+ * full or when the batch timeout expires without losing events.
+ * Wake-up and non wake-up variants of each sensor can be activated at
+ * different rates independently of each other.
+ *
+ * Note: Proximity sensor and significant motion sensor which were defined in
+ * previous releases are also wake-up sensors and must be treated as such.
+ * Wake-up one-shot sensors like SIGNIFICANT_MOTION cannot be batched, hence
+ * the text about batch above doesn't apply to them. See the definitions of
+ * SensorType::PROXIMITY and SensorType::SIGNIFICANT_MOTION for more info.
+ *
+ * Set SENSOR_FLAG_WAKE_UP flag for all wake-up sensors.
+ *
+ * For example, A device can have two sensors both of SensorType::ACCELEROMETER
+ * and one of them can be a wake_up sensor (with SENSOR_FLAG_WAKE_UP flag set)
+ * and the other can be a regular non wake_up sensor. Both of these sensors
+ * must be activated/deactivated independently of the other.
+ */
+
+@export(name="", value_prefix="SENSOR_TYPE_")
+enum SensorType : int32_t {
+    /* META_DATA is a special event type used to populate the MetaData
+     * structure. It doesn't correspond to a physical sensor. Events of this
+     * type exist only inside the HAL, their primary purpose is to signal the
+     * completion of a flush request.
+     */
+    META_DATA                       = 0,
+
+    /*
+     * ACCELEROMETER
+     * reporting-mode: continuous
+     *
+     * All values are in SI units (m/s^2) and measure the acceleration of the
+     * device minus the acceleration due to gravity.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    ACCELEROMETER                   = 1,
+
+    /*
+     * MAGNETIC_FIELD
+     * reporting-mode: continuous
+     *
+     * All values are in micro-Tesla (uT) and measure the geomagnetic
+     * field in the X, Y and Z axis.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    MAGNETIC_FIELD                  = 2,
+
+    /*
+     * ORIENTATION
+     * reporting-mode: continuous
+     *
+     * All values are angles in degrees.
+     *
+     * Orientation sensors return sensor events for all 3 axes at a constant
+     * rate defined by setDelay().
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    ORIENTATION                     = 3,
+
+    /*
+     * GYROSCOPE
+     * reporting-mode: continuous
+     *
+     * All values are in radians/second and measure the rate of rotation
+     * around the X, Y and Z axis.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    GYROSCOPE                       = 4,
+
+    /*
+     * LIGHT
+     * reporting-mode: on-change
+     *
+     * The light sensor value is returned in SI lux units.
+     *
+     * Both wake-up and non wake-up versions are useful.
+     */
+    LIGHT                           = 5,
+
+    /*
+     * PRESSURE
+     * reporting-mode: continuous
+     *
+     * The pressure sensor return the athmospheric pressure in hectopascal (hPa)
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    PRESSURE                        = 6,
+
+    /* TEMPERATURE is deprecated in the HAL */
+    TEMPERATURE                     = 7,
+
+    /*
+     * PROXIMITY
+     * reporting-mode: on-change
+     *
+     * The proximity sensor which turns the screen off and back on during calls
+     * is the wake-up proximity sensor. Implement wake-up proximity sensor
+     * before implementing a non wake-up proximity sensor. For the wake-up
+     * proximity sensor set the flag SENSOR_FLAG_WAKE_UP.
+     * The value corresponds to the distance to the nearest object in
+     * centimeters.
+     */
+    PROXIMITY                       = 8,
+
+    /*
+     * GRAVITY
+     * reporting-mode: continuous
+     *
+     * A gravity output indicates the direction of and magnitude of gravity in
+     * the devices's coordinates.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    GRAVITY                         = 9,
+
+    /*
+     * LINEAR_ACCELERATION
+     * reporting-mode: continuous
+     *
+     * Indicates the linear acceleration of the device in device coordinates,
+     * not including gravity.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    LINEAR_ACCELERATION             = 10,
+
+    /*
+     * ROTATION_VECTOR
+     * reporting-mode: continuous
+     *
+     * The rotation vector symbolizes the orientation of the device relative to
+     * the East-North-Up coordinates frame.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    ROTATION_VECTOR                 = 11,
+
+    /*
+     * RELATIVE_HUMIDITY
+     * reporting-mode: on-change
+     *
+     * A relative humidity sensor measures relative ambient air humidity and
+     * returns a value in percent.
+     *
+     * Both wake-up and non wake-up versions are useful.
+     */
+    RELATIVE_HUMIDITY               = 12,
+
+    /*
+     * AMBIENT_TEMPERATURE
+     * reporting-mode: on-change
+     *
+     * The ambient (room) temperature in degree Celsius.
+     *
+     * Both wake-up and non wake-up versions are useful.
+     */
+    AMBIENT_TEMPERATURE             = 13,
+
+    /*
+     * MAGNETIC_FIELD_UNCALIBRATED
+     * reporting-mode: continuous
+     *
+     * Similar to MAGNETIC_FIELD, but the hard iron calibration is
+     * reported separately instead of being included in the measurement.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    MAGNETIC_FIELD_UNCALIBRATED     = 14,
+
+    /*
+     * GAME_ROTATION_VECTOR
+     * reporting-mode: continuous
+     *
+     * Similar to ROTATION_VECTOR, but not using the geomagnetic
+     * field.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    GAME_ROTATION_VECTOR            = 15,
+
+    /*
+     * GYROSCOPE_UNCALIBRATED
+     * reporting-mode: continuous
+     *
+     * All values are in radians/second and measure the rate of rotation
+     * around the X, Y and Z axis.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    GYROSCOPE_UNCALIBRATED          = 16,
+
+    /*
+     * SIGNIFICANT_MOTION
+     * reporting-mode: one-shot
+     *
+     * A sensor of this type triggers an event each time significant motion
+     * is detected and automatically disables itself.
+     * For Significant Motion sensor to be useful, it must be defined as a
+     * wake-up sensor. (set SENSOR_FLAG_WAKE_UP). Implement the wake-up
+     * significant motion sensor. A non wake-up version is not useful.
+     * The only allowed value to return is 1.0.
+     */
+    SIGNIFICANT_MOTION              = 17,
+
+    /*
+     * STEP_DETECTOR
+     * reporting-mode: special
+     *
+     * A sensor of this type triggers an event each time a step is taken
+     * by the user. The only allowed value to return is 1.0 and an event
+     * is generated for each step.
+     *
+     * Both wake-up and non wake-up versions are useful.
+     */
+    STEP_DETECTOR                   = 18,
+
+    /*
+     * STEP_COUNTER
+     * reporting-mode: on-change
+     *
+     * A sensor of this type returns the number of steps taken by the user since
+     * the last reboot while activated. The value is returned as a uint64_t and
+     * is reset to zero only on a system / android reboot.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    STEP_COUNTER                    = 19,
+
+    /*
+     * GEOMAGNETIC_ROTATION_VECTOR
+     * reporting-mode: continuous
+     *
+     *  Similar to ROTATION_VECTOR, but using a magnetometer instead
+     *  of using a gyroscope.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    GEOMAGNETIC_ROTATION_VECTOR     = 20,
+
+    /*
+     * HEART_RATE
+     * reporting-mode: on-change
+     *
+     *  A sensor of this type returns the current heart rate.
+     *  The events contain the current heart rate in beats per minute (BPM) and
+     *  the status of the sensor during the measurement. See "HeartRate" below
+     *  for more details.
+     *
+     *  Because this sensor is on-change, events must be generated when and only
+     *  when heart_rate.bpm or heart_rate.status have changed since the last
+     *  event. In particular, upon the first activation, unless the device is
+     *  known to not be on the body, the status field of the first event must be
+     *  set to SensorStatus::UNRELIABLE. The event should be generated no faster
+     *  than every period_ns passed to setDelay() or to batch().
+     *  See the definition of the on-change reporting mode for more information.
+     *
+     *  SensorInfo.requiredPermission must be set to
+     *  SENSOR_PERMISSION_BODY_SENSORS.
+     *
+     *  Both wake-up and non wake-up versions are useful.
+     */
+    HEART_RATE                      = 21,
+
+    /*
+     * WAKE_UP_TILT_DETECTOR
+     * reporting-mode: special (setDelay has no impact)
+     *
+     * A sensor of this type generates an event each time a tilt event is
+     * detected. A tilt event must be generated if the direction of the
+     * 2-seconds window average gravity changed by at least 35 degrees since the
+     * activation or the last trigger of the sensor.
+     *
+     *  reference_estimated_gravity = average of accelerometer measurements over
+     *  the first 1 second after activation or the estimated gravity at the last
+     *  trigger.
+     *
+     *  current_estimated_gravity = average of accelerometer measurements over
+     *  the last 2 seconds.
+     *
+     *  trigger when
+     *     angle(reference_estimated_gravity, current_estimated_gravity)
+     *       > 35 degrees
+     *
+     * Large accelerations without a change in phone orientation must not
+     * trigger a tilt event.
+     * For example, a sharp turn or strong acceleration while driving a car
+     * must not trigger a tilt event, even though the angle of the average
+     * acceleration might vary by more than 35 degrees.
+     *
+     * Typically, this sensor is implemented with the help of only an
+     * accelerometer. Other sensors can be used as well if they do not increase
+     * the power consumption significantly. This is a low power sensor that
+     * must allow the AP to go into suspend mode. Do not emulate this sensor
+     * in the HAL.
+     * Like other wake up sensors, the driver is expected to a hold a wake_lock
+     * with a timeout of 200 ms while reporting this event. The only allowed
+     * return value is 1.0.
+     *
+     * Implement only the wake-up version of this sensor.
+     */
+    TILT_DETECTOR                   = 22,
+
+    /*
+     * WAKE_GESTURE
+     * reporting-mode: one-shot
+     *
+     * A sensor enabling waking up the device based on a device specific motion.
+     *
+     * When this sensor triggers, the device behaves as if the power button was
+     * pressed, turning the screen on. This behavior (turning on the screen when
+     * this sensor triggers) might be deactivated by the user in the device
+     * settings. Changes in settings do not impact the behavior of the sensor:
+     * only whether the framework turns the screen on when it triggers.
+     *
+     * The actual gesture to be detected is not specified, and can be chosen by
+     * the manufacturer of the device.
+     * This sensor must be low power, as it is likely to be activated 24/7.
+     * The only allowed value to return is 1.0.
+     *
+     * Implement only the wake-up version of this sensor.
+     */
+    WAKE_GESTURE                    = 23,
+
+    /*
+     * GLANCE_GESTURE
+     * reporting-mode: one-shot
+     *
+     * A sensor enabling briefly turning the screen on to enable the user to
+     * glance content on screen based on a specific motion.  The device must
+     * turn the screen off after a few moments.
+     *
+     * When this sensor triggers, the device turns the screen on momentarily
+     * to allow the user to glance notifications or other content while the
+     * device remains locked in a non-interactive state (dozing). This behavior
+     * (briefly turning on the screen when this sensor triggers) might be
+     * deactivated by the user in the device settings.
+     * Changes in settings do not impact the behavior of the sensor: only
+     * whether the framework briefly turns the screen on when it triggers.
+     *
+     * The actual gesture to be detected is not specified, and can be chosen by
+     * the manufacturer of the device.
+     * This sensor must be low power, as it is likely to be activated 24/7.
+     * The only allowed value to return is 1.0.
+     *
+     * Implement only the wake-up version of this sensor.
+     */
+    GLANCE_GESTURE                  = 24,
+
+    /**
+     * PICK_UP_GESTURE
+     * reporting-mode: one-shot
+     *
+     * A sensor of this type triggers when the device is picked up regardless of
+     * wherever is was before (desk, pocket, bag). The only allowed return value
+     * is 1.0. This sensor de-activates itself immediately after it triggers.
+     *
+     * Implement only the wake-up version of this sensor.
+     */
+    PICK_UP_GESTURE                 = 25,
+
+    /*
+     * WRIST_TILT_GESTURE
+     * trigger-mode: special
+     * wake-up sensor: yes
+     *
+     * A sensor of this type triggers an event each time a tilt of the
+     * wrist-worn device is detected.
+     *
+     * This sensor must be low power, as it is likely to be activated 24/7.
+     * The only allowed value to return is 1.0.
+     *
+     * Implement only the wake-up version of this sensor.
+     */
+    WRIST_TILT_GESTURE              = 26,
+
+    /*
+     * DEVICE_ORIENTATION
+     * reporting-mode: on-change
+     *
+     * The current orientation of the device. The value is reported in
+     * the "scalar" element of the EventPayload in Event. The
+     * only values that can be reported are (please refer to Android Sensor
+     * Coordinate System to understand the X and Y axis direction with respect
+     * to default orientation):
+     *  - 0: device is in default orientation (Y axis is vertical and points up)
+     *  - 1: device is rotated 90 degrees counter-clockwise from default
+     *       orientation (X axis is vertical and points up)
+     *  - 2: device is rotated 180 degrees from default orientation (Y axis is
+     *       vertical and points down)
+     *  - 3: device is rotated 90 degrees clockwise from default orientation
+     *       (X axis is vertical and points down)
+     *
+     * Moving the device to an orientation where the Z axis is vertical (either
+     * up or down) must not cause a new event to be reported.
+     *
+     * To improve the user experience of this sensor, it is recommended to
+     * implement some physical (i.e., rotation angle) and temporal (i.e., delay)
+     * hysteresis. In other words, minor or transient rotations must not cause
+     * a new event to be reported.
+     *
+     * This is a low power sensor that intended to reduce interrupts of
+     * application processor and thus allow it to go sleep. Use hardware
+     * implementation based on low power consumption sensors, such as
+     * accelerometer. Device must not emulate this sensor in the HAL.
+     *
+     * Both wake-up and non wake-up versions are useful.
+     */
+    DEVICE_ORIENTATION              = 27,
+
+    /*
+     * POSE_6DOF
+     * trigger-mode: continuous
+     *
+     * A sensor of this type returns the pose of the device.
+     * Pose of the device is defined as the orientation of the device from a
+     * Earth Centered Earth Fixed frame and the translation from an arbitrary
+     * point at subscription.
+     *
+     * This sensor can be high power. It can use any and all of the following
+     *           . Accelerometer
+     *           . Gyroscope
+     *           . Camera
+     *           . Depth Camera
+     *
+     */
+    POSE_6DOF                       = 28,
+
+    /*
+     * STATIONARY_DETECT
+     * trigger mode: one shot
+     *
+     * A sensor of this type returns an event if the device is still/stationary
+     * for a while. The period of time to monitor for stationarity must be
+     * greater than 5 seconds. The latency must be less than 10 seconds.
+     *
+     * Stationarity here refers to absolute stationarity. eg: device on desk.
+     *
+     * The only allowed value to return is 1.0.
+     */
+    STATIONARY_DETECT               = 29,
+
+    /*
+     * MOTION_DETECT
+     * trigger mode: one shot
+     *
+     * A sensor of this type returns an event if the device is not still for
+     * for a while. The period of time to monitor for stationarity must be
+     * greater than 5 seconds. The latency must be less than 10 seconds.
+     *
+     * Motion here refers to any mechanism in which the device is causes to be
+     * moved in its inertial frame. eg: Pickin up the device and walking with it
+     * to a nearby room may trigger motion wherewas keeping the device on a
+     * table on a smooth train moving at constant velocity may not trigger
+     * motion.
+     *
+     * The only allowed value to return is 1.0.
+     */
+    MOTION_DETECT                   = 30,
+
+    /*
+     * HEART_BEAT
+     * trigger mode: continuous
+     *
+     * A sensor of this type returns an event everytime a hear beat peak is
+     * detected.
+     *
+     * Peak here ideally corresponds to the positive peak in the QRS complex of
+     * and ECG signal.
+     *
+     * The sensor is not expected to be optimized for latency. As a guide, a
+     * latency of up to 10 seconds is acceptable. However, the timestamp attached
+     * to the event must be accuratly correspond to the time the peak occured.
+     *
+     * The sensor event contains a parameter for the confidence in the detection
+     * of the peak where 0.0 represent no information at all, and 1.0 represents
+     * certainty.
+     */
+    HEART_BEAT                      = 31,
+
+    /**
+     * DYNAMIC_SENSOR_META
+     * trigger-mode: special
+     * wake-up sensor: yes
+     *
+     * A sensor event of this type is received when a dynamic sensor is added to
+     * or removed from the system. At most one sensor of this type can be
+     * present in one sensor HAL implementation and presence of a sensor of this
+     * type in sensor HAL implementation indicates that this sensor HAL supports
+     * dynamic sensor feature. Operations, such as batch, activate and setDelay,
+     * to this special purpose sensor must be treated as no-op and return
+     * successful; flush() also has to generate flush complete event as if this
+     * is a sensor that does not support batching.
+     *
+     * A dynamic sensor connection indicates connection of a physical device or
+     * instantiation of a virtual sensor backed by algorithm; and a dynamic
+     * sensor disconnection indicates the the opposite. A sensor event of
+     * DYNAMIC_SENSOR_META type should be delivered regardless of
+     * the activation status of the sensor in the event of dynamic sensor
+     * connection and disconnection. In the sensor event, besides the common
+     * data entries, "dynamic_sensor_meta", which includes fields for connection
+     * status, handle of the sensor involved, pointer to sensor_t structure and
+     * a uuid field, must be populated.
+     *
+     * At a dynamic sensor connection event, fields of sensor_t structure
+     * referenced by a pointer in dynamic_sensor_meta must be filled as if it
+     * was regular sensors. Sensor HAL is responsible for recovery of memory if
+     * the corresponding data is dynamicially allocated. However, the the
+     * pointer must be valid until the first activate call to the sensor
+     * reported in this connection event. At a dynamic sensor disconnection,
+     * the sensor_t pointer must be NULL.
+     *
+     * The sensor handle assigned to dynamic sensors must never be the same as
+     * that of any regular static sensors, and must be unique until next boot.
+     * In another word, if a handle h is used for a dynamic sensor A, that same
+     * number cannot be used for the same dynamic sensor A or another dynamic
+     * sensor B even after disconnection of A until reboot.
+     *
+     * The UUID field will be used for identifying the sensor in addition to
+     * name, vendor and version and type. For physical sensors of the same
+     * model, all sensors will have the same values in sensor_t, but the UUID
+     * must be unique and persistent for each individual unit. An all zero
+     * UUID indicates it is not possible to differentiate individual sensor
+     * unit.
+     *
+     */
+    DYNAMIC_SENSOR_META             = 32,
+
+    /**
+     * ADDITIONAL_INFO
+     * reporting-mode: N/A
+     *
+     * This sensor type is for delivering additional sensor information aside
+     * from sensor event data.
+     * Additional information may include sensor front-end group delay, internal
+     * calibration parameters, noise level metrics, device internal temperature,
+     * etc.
+     *
+     * This type will never bind to a sensor. In other words, no sensor in the
+     * sensor list can have the type SENSOR_TYPE_ADDITIONAL_INFO. If a
+     * sensor HAL supports sensor additional information feature, it reports
+     * sensor_event_t with "sensor" field set to handle of the reporting sensor
+     * and "type" field set to ADDITIONAL_INFO. Delivery of
+     * additional information events is triggered under two conditions: an
+     * enable activate() call or a flush() call to the corresponding sensor.
+     * Besides, time varying parameters can update infrequently without being
+     * triggered. Device is responsible to control update rate. The recommend
+     * update rate is less than 1/1000 of sensor event rate or less than once
+     * per minute in average.
+     *
+     * A single additional information report consists of multiple frames.
+     * Sequences of these frames are ordered using timestamps, which means the
+     * timestamps of sequential frames have to be at least 1 nanosecond apart
+     * from each other. Each frame is a sensor_event_t delivered through the HAL
+     * interface, with related data stored in the "additional_info" field, which
+     * is of type additional_info_event_t.
+     * The "type" field of additional_info_event_t denotes the nature of the
+     * payload data (see additional_info_type_t).
+     * The "serial" field is used to keep the sequence of payload data that
+     * spans multiple frames. The first frame of the entire report is always of
+     * type AINFO_BEGIN, and the last frame is always AINFO_END.
+     *
+     * If flush() was triggering the report, all additional information frames
+     * must be delivered after flush complete event.
+     */
+    ADDITIONAL_INFO                 = 33,
+
+    /*
+     * LOW_LATENCY_OFFBODY_DETECT
+     * trigger-mode: on-change
+     * wake-up sensor: yes
+     *
+     * A sensor of this type is defined for devices that are supposed to be worn
+     * by the user in the normal use case (such as a watch, wristband, etc) and
+     * is not yet defined for other device.
+     *
+     * A sensor of this type triggers an event each time the wearable device
+     * is removed from the body and each time it's put back onto the body.
+     * It must be low-latency and be able to detect the on-body to off-body
+     * transition within one second (event delivery time included),
+     * and 3-second latency to determine the off-body to on-body transition
+     * (event delivery time included).
+     *
+     * There are only two valid event values for the sensor to return :
+     *    0.0 for off-body
+     *    1.0 for on-body
+     *
+     */
+    LOW_LATENCY_OFFBODY_DETECT      = 34,
+
+    /*
+     * ACCELEROMETER_UNCALIBRATED
+     * reporting-mode: continuous
+     *
+     * All values are in SI units (m/s^2) and measure the acceleration of the
+     * device minus the acceleration due to gravity.
+     *
+     * Implement the non-wake-up version of this sensor and implement the
+     * wake-up version if the system possesses a wake up fifo.
+     */
+    ACCELEROMETER_UNCALIBRATED      = 35,
+
+    /*
+     * Base for device manufacturers private sensor types.
+     * These sensor types can't be exposed in the SDK.
+     */
+    DEVICE_PRIVATE_BASE             = 0x10000
+};
+
+@export(name="", value_prefix="SENSOR_FLAG_")
+enum SensorFlagBits : uint32_t {
+    /*
+     * Whether this sensor wakes up the AP from suspend mode when data is
+     * available.  Whenever sensor events are delivered from a wake_up sensor,
+     * the driver needs to hold a wake_lock till the events are read by the
+     * SensorService i.e till ISensors::poll() is called the next time.
+     * Once poll is called again it means events have been read by the
+     * SensorService, the driver can safely release the wake_lock. SensorService
+     * will continue to hold a wake_lock till the app actually reads the events.
+     */
+    WAKE_UP                     = 1,
+
+    /*
+     * Reporting modes for various sensors. Each sensor will have exactly one of
+     * these modes set.
+     * The least significant 2nd, 3rd and 4th bits are used to represent four
+     * possible reporting modes.
+     */
+    CONTINUOUS_MODE             = 0,
+    ON_CHANGE_MODE              = 2,
+    ONE_SHOT_MODE               = 4,
+    SPECIAL_REPORTING_MODE      = 6,
+
+    /*
+     * Set this flag if the sensor supports data_injection mode and allows data
+     * to be injected from the SensorService. When in data_injection ONLY
+     * sensors with this flag set are injected sensor data and only sensors with
+     * this flag set are activated. Eg: Accelerometer and Step Counter sensors
+     * can be set with this flag and SensorService will inject accelerometer
+     * data and read the corresponding step counts.
+     */
+    DATA_INJECTION              = 0x10,
+
+    /*
+     * Set this flag if the sensor is a dynamically connected sensor. See
+     * DynamicSensorInfo and DYNAMIC_SENSOR_META for details.
+     */
+    DYNAMIC_SENSOR              = 0x20,
+
+    /*
+     * Set this flag if sensor additional information is supported.
+     * See ADDITIONAL_INFO and AdditionalInfo for details.
+     */
+    ADDITIONAL_INFO             = 0x40,
+
+    /*
+     * Set this flag if sensor suppor direct channel backed by ashmem.
+     * See SharedMemType and registerDirectChannel for more details.
+     */
+    DIRECT_CHANNEL_ASHMEM       = 0x400,
+
+    /*
+     * Set this flag if sensor suppor direct channel backed by gralloc HAL memory.
+     * See SharedMemType and registerDirectChannel for more details.
+     */
+    DIRECT_CHANNEL_GRALLOC      = 0x800,
+
+    /*
+     * Flags mask for reporting mode of sensor.
+     */
+    MASK_REPORTING_MODE         = 0xE,
+
+    /*
+     * Flags mask for direct report maximum rate level support.
+     * See RateLevel.
+     */
+    MASK_DIRECT_REPORT          = 0x380,
+
+    /*
+     * Flags mask for all direct channel support bits.
+     * See SharedMemType.
+     */
+    MASK_DIRECT_CHANNEL         = 0xC00,
+};
+
+@export(name="sensor_flag_shift_t", value_prefix="SENSOR_FLAG_SHIFT_")
+enum SensorFlagShift : uint8_t {
+    REPORTING_MODE              = 1,
+    DATA_INJECTION              = 4,
+    DYNAMIC_SENSOR              = 5,
+    ADDITIONAL_INFO             = 6,
+    DIRECT_REPORT               = 7,
+    DIRECT_CHANNEL              = 10,
+};
+
+struct SensorInfo {
+    /* handle that identifies this sensors. This handle is used to reference
+     * this sensor throughout the HAL API.
+     */
+    int32_t sensorHandle;
+
+    /* Name of this sensor.
+     * All sensors of the same "type" must have a different "name".
+     */
+    string name;
+
+    /* vendor of the hardware part */
+    string vendor;
+
+    /* version of the hardware part + driver. The value of this field
+     * must increase when the driver is updated in a way that changes the
+     * output of this sensor. This is important for fused sensors when the
+     * fusion algorithm is updated.
+     */
+    int32_t version;
+
+    /* this sensor's type. */
+    SensorType type;
+
+    /* type of this sensor as a string.
+     *
+     * When defining an OEM specific sensor or sensor manufacturer specific
+     * sensor, use your reserve domain name as a prefix.
+     * e.g. com.google.glass.onheaddetector
+     *
+     * For sensors of known type defined in SensorType (value <
+     * SensorType::DEVICE_PRIVATE_BASE), this can be an empty string.
+     */
+    string typeAsString;
+
+    /* maximum range of this sensor's value in SI units */
+    float maxRange;
+
+    /* smallest difference between two values reported by this sensor */
+    float resolution;
+
+    /* rough estimate of this sensor's power consumption in mA */
+    float power;
+
+    /* this value depends on the reporting mode:
+     *
+     *   continuous: minimum sample period allowed in microseconds
+     *   on-change : 0
+     *   one-shot  :-1
+     *   special   : 0, unless otherwise noted
+     */
+    int32_t minDelay;
+
+    /* number of events reserved for this sensor in the batch mode FIFO.
+     * If there is a dedicated FIFO for this sensor, then this is the
+     * size of this FIFO. If the FIFO is shared with other sensors,
+     * this is the size reserved for that sensor and it can be zero.
+     */
+    uint32_t fifoReservedEventCount;
+
+    /* maximum number of events of this sensor that could be batched.
+     * This is especially relevant when the FIFO is shared between
+     * several sensors; this value is then set to the size of that FIFO.
+     */
+    uint32_t fifoMaxEventCount;
+
+    /* permission required to see this sensor, register to it and receive data.
+     * Set to "" if no permission is required. Some sensor types like the
+     * heart rate monitor have a mandatory require_permission.
+     * For sensors that always require a specific permission, like the heart
+     * rate monitor, the android framework might overwrite this string
+     * automatically.
+     */
+    string requiredPermission;
+
+    /* This value is defined only for continuous mode and on-change sensors.
+     * It is the delay between two sensor events corresponding to the lowest
+     * frequency that this sensor supports. When lower frequencies are requested
+     * through batch()/setDelay() the events will be generated at this frequency
+     * instead.
+     * It can be used by the framework or applications to estimate when the
+     * batch FIFO may be full.
+     *
+     * NOTE: periodNs is in nanoseconds where as maxDelay/minDelay are in
+     *       microseconds.
+     *
+     *       continuous, on-change: maximum sampling period allowed in
+     *                              microseconds.
+     *
+     *          one-shot, special : 0
+     */
+    int32_t maxDelay;
+
+    /* Bitmask of SensorFlagBits */
+    bitfield<SensorFlagBits> flags;
+};
+
+@export(name="", value_prefix="SENSOR_STATUS_")
+enum SensorStatus : int8_t {
+    NO_CONTACT          = -1,
+    UNRELIABLE          = 0,
+    ACCURACY_LOW        = 1,
+    ACCURACY_MEDIUM     = 2,
+    ACCURACY_HIGH       = 3,
+};
+
+struct Vec3 {
+    float x;
+    float y;
+    float z;
+    SensorStatus status;
+};
+
+struct Vec4 {
+    float x;
+    float y;
+    float z;
+    float w;
+};
+
+struct Uncal {
+    float x;
+    float y;
+    float z;
+    float x_bias;
+    float y_bias;
+    float z_bias;
+};
+
+struct HeartRate {
+    /* Heart rate in beats per minute.
+     * Set to 0 when status is SensorStatus::UNRELIABLE or
+     * SensorStatus::NO_CONTACT
+     */
+    float bpm;
+
+    /* Status of the heart rate sensor for this reading. */
+    SensorStatus status;
+};
+
+@export(name="")
+enum MetaDataEventType : uint32_t {
+    META_DATA_FLUSH_COMPLETE = 1,
+};
+
+struct MetaData {
+    MetaDataEventType what;
+};
+
+struct DynamicSensorInfo {
+    bool connected;
+    int32_t sensorHandle;
+
+    /* UUID of a dynamic sensor (using RFC 4122 byte order)
+     * For UUID 12345678-90AB-CDEF-1122-334455667788 the uuid field is
+     * initialized as:
+     *   {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x11, ...}
+     */
+    uint8_t[16] uuid;
+};
+
+@export(name="additional_info_type_t")
+enum AdditionalInfoType : uint32_t {
+    /* Marks the beginning of additional information frames */
+    AINFO_BEGIN                       = 0,
+
+    /* Marks the end of additional information frames */
+    AINFO_END                         = 1,
+
+    /* Estimation of the delay that is not tracked by sensor timestamps. This
+     * includes delay introduced by sensor front-end filtering, data transport,
+     * etc.
+     * float[2]: delay in seconds, standard deviation of estimated value
+     */
+    AINFO_UNTRACKED_DELAY             = 0x10000,
+
+    /* float: Celsius temperature */
+    AINFO_INTERNAL_TEMPERATURE,
+
+    /* First three rows of a homogeneous matrix, which represents calibration to
+     * a three-element vector raw sensor reading.
+     * float[12]: 3x4 matrix in row major order
+     */
+    AINFO_VEC3_CALIBRATION,
+
+    /* Location and orientation of sensor element in the device frame: origin is
+     * the geometric center of the mobile device screen surface; the axis
+     * definition corresponds to Android sensor definitions.
+     * float[12]: 3x4 matrix in row major order
+     */
+    AINFO_SENSOR_PLACEMENT,
+
+    /* float[2]: raw sample period in seconds,
+     *           standard deviation of sampling period
+     */
+    AINFO_SAMPLING,
+
+    // Sampling channel modeling information section
+
+    /* int32_t: noise type
+     * float[n]: parameters
+     */
+    AINFO_CHANNEL_NOISE               = 0x20000,
+
+    /* float[3]: sample period, standard deviation of sample period,
+     * quantization unit
+     */
+    AINFO_CHANNEL_SAMPLER,
+
+    /* Represents a filter:
+     *   \sum_j a_j y[n-j] == \sum_i b_i x[n-i]
+     *
+     * int32_t[3]: number of feedforward coeffients M,
+     *             number of feedback coefficients N (for FIR filter, N = 1).
+     *             bit mask that represents which element the filter is applied
+     *             to. (bit 0==1 means this filter applies to vector element 0).
+     * float[M+N]: filter coefficients (b0, b1, ..., b_{M-1}), then
+     *             (a0, a1, ..., a_{N-1}), a0 is always 1.
+     *
+     * Multiple frames may be needed for higher number of taps.
+     */
+    AINFO_CHANNEL_FILTER,
+
+    /* int32_t[2]: size in (row, column) ... 1st frame
+     * float[n]: matrix element values in row major order.
+     */
+    AINFO_CHANNEL_LINEAR_TRANSFORM,
+
+    /* int32_t[2]: extrapolate method, interpolate method
+     * float[n]: mapping key points in pairs, (in, out)...
+     *           (may be used to model saturation).
+     */
+    AINFO_CHANNEL_NONLINEAR_MAP,
+
+    /* int32_t: resample method (0-th order, 1st order...)
+     * float[1]: resample ratio (upsampling if < 1.0, downsampling if > 1.0).
+     */
+    AINFO_CHANNEL_RESAMPLER,
+
+    /* Operation environment parameters section
+     * Types in the following section is sent down (instead of reported from)
+     * device as additional information to aid sensor operation. Data is sent
+     * via injectSensorData() function to sensor handle -1 denoting all sensors
+     * in device.
+     */
+
+    /* Local geomagnetic field information based on device geo location. This
+     * type is primarily for for magnetic field calibration and rotation vector
+     * sensor fusion.
+     * float[3]: strength (uT), declination and inclination angle (rad).
+     */
+    AINFO_LOCAL_GEOMAGNETIC_FIELD     = 0x30000,
+
+    /* Local gravitational acceleration strength at device geo location.
+     * float: gravitational acceleration norm in m/s^2.
+     */
+    AINFO_LOCAL_GRAVITY,
+
+    /* Device dock state.
+     * int32_t: dock state following Android API Intent.EXTRA_DOCK_STATE
+     * definition, undefined value is ignored.
+     */
+    AINFO_DOCK_STATE,
+
+    /* High performance mode hint. Device is able to use up more power and take
+     * more reources to improve throughput and latency in high performance mode.
+     * One possible use case is virtual reality, when sensor latency need to be
+     * carefully controlled.
+     * int32_t: 1 or 0, denote if device is in/out of high performance mode,
+     *          other values is ignored.
+     */
+    AINFO_HIGH_PERFORMANCE_MODE,
+
+    /* Magnetic field calibration hint. Device is notified when manually
+     * triggered magnetic field calibration procedure is started or stopped. The
+     * calibration procedure is assumed timed out after 1 minute from start,
+     * even if an explicit stop is not received.
+     *
+     * int32_t: 1 for start, 0 for stop, other value is ignored.
+     */
+    AINFO_MAGNETIC_FIELD_CALIBRATION,
+
+    /* Custom information */
+    AINFO_CUSTOM_START                = 0x10000000,
+
+    /* Debugging */
+    AINFO_DEBUGGING_START             = 0x40000000,
+};
+
+struct AdditionalInfo {
+    /* type of payload data, see AdditionalInfoType */
+    AdditionalInfoType type;
+
+    /* sequence number of this frame for this type */
+    int32_t serial;
+
+    union Payload {
+        int32_t[14] data_int32;
+        float[14] data_float;
+    } u;
+};
+
+/* acceleration values are in meter per second per second (m/s^2)
+ * magnetic vector values are in micro-Tesla (uT)
+ * orientation values are in degrees
+ * gyroscope values are in rad/s
+ * temperature is in degrees centigrade (Celsius)
+ * distance in centimeters
+ * light in SI lux units
+ * pressure in hectopascal (hPa)
+ * relative humidity in percent
+ */
+union EventPayload {
+    /* SensorType::ACCELEROMETER, SensorType::MAGNETIC_FIELD,
+     * SensorType::ORIENTATION, SensorType::GYROSCOPE, SensorType::GRAVITY,
+     * SensorType::LINEAR_ACCELERATION
+     */
+    Vec3 vec3;
+
+    /* SensorType::ROTATION_VECTOR, SensorType::GAME_ROTATION_VECTOR,
+     * SensorType::GEOMAGNETIC_ROTATION_VECTOR
+     */
+    Vec4 vec4;
+
+    /* SensorType::MAGNETIC_FIELD_UNCALIBRATED,
+     * SensorType::GYROSCOPE_UNCALIBRATED
+     * SensorType::ACCELEROMETER_UNCALIBRATED
+     */
+    Uncal uncal;
+
+    /* SensorType::META_DATA */
+    MetaData meta;
+
+    /* SensorType::DEVICE_ORIENTATION, SensorType::LIGHT, SensorType::PRESSURE,
+     * SensorType::TEMPERATURE, SensorType::PROXIMITY,
+     * SensorType::RELATIVE_HUMIDITY, SensorType::AMBIENT_TEMPERATURE,
+     * SensorType::SIGNIFICANT_MOTION, SensorType::STEP_DETECTOR,
+     * SensorType::TILT_DETECTOR, SensorType::WAKE_GESTURE,
+     * SensorType::GLANCE_GESTURE, SensorType::PICK_UP_GESTURE,
+     * SensorType::WRIST_TILT_GESTURE, SensorType::STATIONARY_DETECT,
+     * SensorType::MOTION_DETECT, SensorType::HEART_BEAT
+     */
+    float scalar;
+
+    /* SensorType::STEP_COUNTER */
+    uint64_t stepCount;
+
+    /* SensorType::HEART_RATE */
+    HeartRate heartRate;
+
+    /* SensorType::POSE_6DOF */
+    float[15] pose6DOF;
+
+    /* SensorType::DYNAMIC_SENSOR_META */
+    DynamicSensorInfo dynamic;
+
+    /* SensorType::ADDITIONAL_INFO */
+    AdditionalInfo additional;
+
+    /* undefined/custom sensor type >= SensorType::DEVICE_PRIVATE_BASE */
+    float[16] data;
+};
+
+struct Event {
+    /* Time measured in nanoseconds, in "elapsedRealtimeNano()'s" timebase. */
+    int64_t timestamp;
+
+    /* sensor identifier */
+    int32_t sensorHandle;
+
+    SensorType sensorType;
+
+    /* Union discriminated on sensorType */
+    EventPayload u;
+};
+
+/**
+ * Direct report rate level definition. Except for SENSOR_DIRECT_RATE_STOP, each
+ * rate level covers the range (55%, 220%] * nominal report rate. For example,
+ * if config direct report specify a rate level SENSOR_DIRECT_RATE_FAST, it is
+ * legal for sensor hardware to report event at a rate greater than 110Hz, and
+ * less or equal to 440Hz. Note that rate has to remain steady without variation
+ * before new rate level is configured, i.e. if a sensor is configured to
+ * SENSOR_DIRECT_RATE_FAST and starts to report event at 256Hz, it cannot
+ * change rate to 128Hz after a few seconds of running even if 128Hz is also in
+ * the legal range of SENSOR_DIRECT_RATE_FAST. Thus, it is recommended to
+ * associate report rate with RateLvel statically for single sensor.
+ */
+@export(name="direct_rate_level_t", value_prefix="SENSOR_DIRECT_RATE_")
+enum RateLevel : int32_t {
+    STOP,            // stop
+    NORMAL,          // nominal 50Hz
+    FAST,            // nominal 200Hz
+    VERY_FAST,       // nominal 800Hz
+};
+
+/**
+ * Direct channel shared memory types. See struct SharedMemInfo.
+ */
+@export(name="direct_mem_type_t", value_prefix="SENSOR_DIRECT_MEM_TYPE_")
+enum SharedMemType : int32_t {
+    // handle contains 1 fd (ashmem handle) and 0 int.
+    ASHMEM = 1,
+    // handle definition matches gralloc HAL.
+    GRALLOC
+};
+
+
+/**
+ * Direct channel lock-free queue format, this defines how the shared memory is
+ * interpreted by both sensor hardware and application.
+ *
+ * @see SharedMemInfo.
+ */
+@export(name="direct_format_t", value_prefix="SENSOR_DIRECT_FMT_")
+enum SharedMemFormat : int32_t {
+    SENSORS_EVENT = 1,  // shared memory is formated as an array of data
+                        // elements. See SensorsEventFormatOffset for details.
+                        // Upon return of channel registration call, the
+                        // shared memory space must be formated to all 0 by HAL.
+};
+
+enum SensorsEventFormatOffset : uint16_t {
+    // offset   type        name
+    //-----------------------------------
+    // 0x0000   int32_t     size (always 104)
+    // 0x0004   int32_t     sensor report token
+    // 0x0008   int32_t     type (see SensorType)
+    // 0x000C   uint32_t    atomic counter
+    // 0x0010   int64_t     timestamp (see Event)
+    // 0x0018   float[16]/  data
+    //          int64_t[8]
+    // 0x0058   int32_t[4]  reserved (set to zero)
+    SIZE_FIELD      = 0x0,
+    REPORT_TOKEN    = 0x4,
+    SENSOR_TYPE     = 0x8,
+    ATOMIC_COUNTER  = 0xC,
+    TIMESTAMP       = 0x10,
+    DATA            = 0x18,
+    RESERVED        = 0x58,
+    TOTAL_LENGTH    = 0x68
+};
+
+/**
+ * Shared memory information for a direct channel
+ */
+struct SharedMemInfo {
+    SharedMemType type;         // shared memory type
+    SharedMemFormat format;
+    uint32_t size;              // size of the memory region, in bytes
+    handle memoryHandle;        // shared memory handle, it is interpreted
+                                // depending on type field, see SharedMemType.
+};
diff --git a/sensors/1.0/vts/Android.mk b/sensors/1.0/vts/Android.mk
new file mode 100644
index 0000000..e22fba7
--- /dev/null
+++ b/sensors/1.0/vts/Android.mk
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# include hidl test makefiles
+include $(LOCAL_PATH)/functional/vts/testcases/hal/sensors/hidl/Android.mk
diff --git a/sensors/1.0/vts/Sensors.vts b/sensors/1.0/vts/Sensors.vts
new file mode 100644
index 0000000..9e90755
--- /dev/null
+++ b/sensors/1.0/vts/Sensors.vts
@@ -0,0 +1,171 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "ISensors"
+
+package: "android.hardware.sensors"
+
+import: "android.hardware.sensors@1.0::types"
+
+interface: {
+    api: {
+        name: "getSensorsList"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::sensors::V1_0::SensorInfo"
+            }
+        }
+    }
+
+    api: {
+        name: "setOperationMode"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::OperationMode"
+        }
+    }
+
+    api: {
+        name: "activate"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+    }
+
+    api: {
+        name: "poll"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::sensors::V1_0::Event"
+            }
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::sensors::V1_0::SensorInfo"
+            }
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "batch"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int64_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int64_t"
+        }
+    }
+
+    api: {
+        name: "flush"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "injectSensorData"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::sensors::V1_0::Event"
+        }
+    }
+
+    api: {
+        name: "registerDirectChannel"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::sensors::V1_0::SharedMemInfo"
+        }
+    }
+
+    api: {
+        name: "unregisterDirectChannel"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+    api: {
+        name: "configDirectReport"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::sensors::V1_0::RateLevel"
+        }
+    }
+
+}
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..9ca6230
--- /dev/null
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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_test {
+    name: "sensors_hidl_hal_test",
+    gtest: true,
+    srcs: ["sensors_hidl_hal_test.cpp"],
+    shared_libs: [
+        "android.hardware.sensors@1.0",
+        "libcutils",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
+
diff --git a/sensors/1.0/vts/functional/sensors_hidl_hal_test.cpp b/sensors/1.0/vts/functional/sensors_hidl_hal_test.cpp
new file mode 100644
index 0000000..9a71745
--- /dev/null
+++ b/sensors/1.0/vts/functional/sensors_hidl_hal_test.cpp
@@ -0,0 +1,1009 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "sensors_hidl_hal_test"
+#include <android-base/logging.h>
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <android/log.h>
+#include <cutils/ashmem.h>
+#include <gtest/gtest.h>
+#include <hardware/sensors.h>       // for sensor type strings
+
+#include <algorithm>
+#include <cinttypes>
+#include <cmath>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <unordered_set>
+#include <vector>
+
+#include <sys/mman.h>
+#include <unistd.h>
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using namespace ::android::hardware::sensors::V1_0;
+
+// Test environment for sensors
+class SensorsHidlEnvironment : public ::testing::Environment {
+ public:
+  // get the test environment singleton
+  static SensorsHidlEnvironment* Instance() {
+    static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
+    return instance;
+  }
+
+  // sensors hidl service
+  sp<ISensors> sensors;
+
+  virtual void SetUp();
+  virtual void TearDown();
+
+  // Get and clear all events collected so far (like "cat" shell command).
+  // If output is nullptr, it clears all collected events.
+  void catEvents(std::vector<Event>* output);
+
+  // set sensor event collection status
+  void setCollection(bool enable);
+
+ private:
+  SensorsHidlEnvironment() {}
+
+  void addEvent(const Event& ev);
+  void startPollingThread();
+  static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);
+
+  bool collectionEnabled;
+  std::shared_ptr<bool> stopThread;
+  std::thread pollThread;
+  std::vector<Event> events;
+  std::mutex events_mutex;
+
+  GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
+};
+
+void SensorsHidlEnvironment::SetUp() {
+  sensors = ISensors::getService();
+  ALOGI_IF(sensors, "sensors is not nullptr, %p", sensors.get());
+  ASSERT_NE(sensors, nullptr);
+
+  collectionEnabled = false;
+  startPollingThread();
+
+  // In case framework just stopped for test and there is sensor events in the pipe,
+  // wait some time for those events to be cleared to avoid them messing up the test.
+  std::this_thread::sleep_for(std::chrono::seconds(3));
+}
+
+void SensorsHidlEnvironment::TearDown() {
+  ALOGI("TearDown SensorsHidlEnvironement");
+
+  if (stopThread) {
+    *stopThread = true;
+  }
+  pollThread.detach();
+}
+
+void SensorsHidlEnvironment::catEvents(std::vector<Event>* output) {
+  std::lock_guard<std::mutex> lock(events_mutex);
+  if (output) {
+    output->insert(output->end(), events.begin(), events.end());
+  }
+  events.clear();
+}
+
+void SensorsHidlEnvironment::setCollection(bool enable) {
+  std::lock_guard<std::mutex> lock(events_mutex);
+  collectionEnabled = enable;
+}
+
+void SensorsHidlEnvironment::addEvent(const Event& ev) {
+  std::lock_guard<std::mutex> lock(events_mutex);
+  if (collectionEnabled) {
+    events.push_back(ev);
+  }
+}
+
+void SensorsHidlEnvironment::startPollingThread() {
+  stopThread = std::shared_ptr<bool>(new bool(false));
+  pollThread = std::thread(pollingThread, this, stopThread);
+  events.reserve(128);
+}
+
+void SensorsHidlEnvironment::pollingThread(
+    SensorsHidlEnvironment* env, std::shared_ptr<bool> stop) {
+  ALOGD("polling thread start");
+  bool needExit = *stop;
+
+  while(!needExit) {
+    env->sensors->poll(1,
+        [&](auto result, const auto &events, const auto &dynamicSensorsAdded) {
+          if (result != Result::OK
+              || (events.size() == 0 && dynamicSensorsAdded.size() == 0)
+              || *stop) {
+            needExit = true;
+            return;
+          }
+
+          if (events.size() > 0) {
+            env->addEvent(events[0]);
+          }
+        });
+  }
+  ALOGD("polling thread end");
+}
+
+class SensorsTestSharedMemory {
+ public:
+  static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
+  SharedMemInfo getSharedMemInfo() const;
+  char * getBuffer() const;
+  std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
+  virtual ~SensorsTestSharedMemory();
+ private:
+  SensorsTestSharedMemory(SharedMemType type, size_t size);
+
+  SharedMemType mType;
+  native_handle_t* mNativeHandle;
+  size_t mSize;
+  char* mBuffer;
+
+  DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
+};
+
+SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
+  SharedMemInfo mem = {
+    .type = mType,
+    .format = SharedMemFormat::SENSORS_EVENT,
+    .size = static_cast<uint32_t>(mSize),
+    .memoryHandle = mNativeHandle
+  };
+  return mem;
+}
+
+char * SensorsTestSharedMemory::getBuffer() const {
+  return mBuffer;
+}
+
+std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
+
+  constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+  constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
+  constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
+  constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
+  constexpr size_t kOffsetAtomicCounter =
+      static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
+  constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
+  constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
+
+  std::vector<Event> events;
+  std::vector<float> data(16);
+
+  while (offset + kEventSize <= mSize) {
+    int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter);
+    if (atomicCounter <= lastCounter) {
+      break;
+    }
+
+    int32_t size = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetSize);
+    if (size != kEventSize) {
+      // unknown error, events parsed may be wrong, remove all
+      events.clear();
+      break;
+    }
+
+    int32_t token = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetToken);
+    int32_t type = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetType);
+    int64_t timestamp = *reinterpret_cast<int64_t *>(mBuffer + offset + kOffsetTimestamp);
+
+    ALOGV("offset = %zu, cnt %" PRId32 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64,
+        offset, atomicCounter, token, type, timestamp);
+
+    Event event = {
+      .timestamp = timestamp,
+      .sensorHandle = token,
+      .sensorType = static_cast<SensorType>(type),
+    };
+    event.u.data = android::hardware::hidl_array<float, 16>
+        (reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
+
+    events.push_back(event);
+
+    lastCounter = atomicCounter;
+    offset += kEventSize;
+  }
+
+  return events;
+}
+
+SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
+    : mType(type), mSize(0), mBuffer(nullptr) {
+  native_handle_t *handle = nullptr;
+  char *buffer = nullptr;
+  switch(type) {
+    case SharedMemType::ASHMEM: {
+      int fd;
+      handle = ::native_handle_create(1 /*nFds*/, 0/*nInts*/);
+      if (handle != nullptr) {
+        handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
+        if (handle->data[0] > 0) {
+          // memory is pinned by default
+          buffer = static_cast<char *>
+              (::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+          if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
+            break;
+          }
+          ::native_handle_close(handle);
+        }
+        ::native_handle_delete(handle);
+        handle = nullptr;
+      }
+      break;
+    }
+    default:
+      break;
+  }
+
+  if (buffer != nullptr) {
+    mNativeHandle = handle;
+    mSize = size;
+    mBuffer = buffer;
+  }
+}
+
+SensorsTestSharedMemory::~SensorsTestSharedMemory() {
+  switch(mType) {
+    case SharedMemType::ASHMEM: {
+      if (mSize != 0) {
+        ::munmap(mBuffer, mSize);
+        mBuffer = nullptr;
+
+        ::native_handle_close(mNativeHandle);
+        ::native_handle_delete(mNativeHandle);
+
+        mNativeHandle = nullptr;
+        mSize = 0;
+      }
+      break;
+    }
+    default: {
+      if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
+        ALOGE("SensorsTestSharedMemory %p not properly destructed: "
+            "type %d, native handle %p, size %zu, buffer %p",
+            this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+      }
+      break;
+    }
+  }
+}
+
+SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
+  constexpr size_t kMaxSize = 128*1024*1024; // sensor test should not need more than 128M
+  if (size == 0 || size >= kMaxSize) {
+    return nullptr;
+  }
+
+  auto m = new SensorsTestSharedMemory(type, size);
+  if (m->mSize != size || m->mBuffer == nullptr) {
+    delete m;
+    m = nullptr;
+  }
+  return m;
+}
+
+// The main test class for SENSORS HIDL HAL.
+class SensorsHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+  }
+
+  virtual void TearDown() override {
+    // stop all sensors
+    for (auto s : mSensorHandles) {
+      S()->activate(s, false);
+    }
+    mSensorHandles.clear();
+
+    // stop all direct report and channels
+    for (auto c : mDirectChannelHandles) {
+      // disable all reports
+      S()->configDirectReport(-1, c, RateLevel::STOP, [] (auto, auto){});
+      S()->unregisterDirectChannel(c);
+    }
+    mDirectChannelHandles.clear();
+  }
+
+ protected:
+  SensorInfo defaultSensorByType(SensorType type);
+  std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+        bool clearBeforeStart = true, bool changeCollection = true);
+
+  // implementation wrapper
+  Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) {
+    return S()->getSensorsList(_hidl_cb);
+  }
+
+  Return<Result> activate(
+          int32_t sensorHandle, bool enabled);
+
+  Return<Result> batch(
+          int32_t sensorHandle,
+          int64_t samplingPeriodNs,
+          int64_t maxReportLatencyNs) {
+    return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+  }
+
+  Return<Result> flush(int32_t sensorHandle) {
+    return S()->flush(sensorHandle);
+  }
+
+  Return<Result> injectSensorData(const Event& event) {
+    return S()->injectSensorData(event);
+  }
+
+  Return<void> registerDirectChannel(
+          const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb);
+
+  Return<Result> unregisterDirectChannel(int32_t channelHandle) {
+    return S()->unregisterDirectChannel(channelHandle);
+  }
+
+  Return<void> configDirectReport(
+          int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+          ISensors::configDirectReport_cb _hidl_cb) {
+    return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+  }
+
+  inline sp<ISensors>& S() {
+    return SensorsHidlEnvironment::Instance()->sensors;
+  }
+
+  inline static SensorFlagBits extractReportMode(uint64_t flag) {
+    return (SensorFlagBits) (flag
+        & ((uint64_t) SensorFlagBits::CONTINUOUS_MODE
+          | (uint64_t) SensorFlagBits::ON_CHANGE_MODE
+          | (uint64_t) SensorFlagBits::ONE_SHOT_MODE
+          | (uint64_t) SensorFlagBits::SPECIAL_REPORTING_MODE));
+  }
+
+  inline static bool isMetaSensorType(SensorType type) {
+    return (type == SensorType::META_DATA
+            || type == SensorType::DYNAMIC_SENSOR_META
+            || type == SensorType::ADDITIONAL_INFO);
+  }
+
+  inline static bool isValidType(SensorType type) {
+    return (int32_t) type > 0;
+  }
+
+  static bool typeMatchStringType(SensorType type, const hidl_string& stringType);
+  static bool typeMatchReportMode(SensorType type, SensorFlagBits reportMode);
+  static bool delayMatchReportMode(int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode);
+  static SensorFlagBits expectedReportModeForType(SensorType type);
+
+  // all sensors and direct channnels used
+  std::unordered_set<int32_t> mSensorHandles;
+  std::unordered_set<int32_t> mDirectChannelHandles;
+};
+
+
+Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
+  // If activating a sensor, add the handle in a set so that when test fails it can be turned off.
+  // The handle is not removed when it is deactivating on purpose so that it is not necessary to
+  // check the return value of deactivation. Deactivating a sensor more than once does not have
+  // negative effect.
+  if (enabled) {
+    mSensorHandles.insert(sensorHandle);
+  }
+  return S()->activate(sensorHandle, enabled);
+}
+
+Return<void> SensorsHidlTest::registerDirectChannel(
+    const SharedMemInfo& mem, ISensors::registerDirectChannel_cb cb) {
+  // If registeration of a channel succeeds, add the handle of channel to a set so that it can be
+  // unregistered when test fails. Unregister a channel does not remove the handle on purpose.
+  // Unregistering a channel more than once should not have negative effect.
+  S()->registerDirectChannel(mem,
+      [&] (auto result, auto channelHandle) {
+        if (result == Result::OK) {
+          mDirectChannelHandles.insert(channelHandle);
+        }
+        cb(result, channelHandle);
+      });
+  return Void();
+}
+
+std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+      bool clearBeforeStart, bool changeCollection) {
+  std::vector<Event> events;
+  constexpr useconds_t SLEEP_GRANULARITY = 100*1000; //gradularity 100 ms
+
+  ALOGI("collect max of %zu events for %d us, clearBeforeStart %d",
+        nEventLimit, timeLimitUs, clearBeforeStart);
+
+  if (changeCollection) {
+    SensorsHidlEnvironment::Instance()->setCollection(true);
+  }
+  if (clearBeforeStart) {
+    SensorsHidlEnvironment::Instance()->catEvents(nullptr);
+  }
+
+  while (timeLimitUs > 0) {
+    useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
+    usleep(duration);
+    timeLimitUs -= duration;
+
+    SensorsHidlEnvironment::Instance()->catEvents(&events);
+    if (events.size() >= nEventLimit) {
+      break;
+    }
+    ALOGV("time to go = %d, events to go = %d",
+          (int)timeLimitUs, (int)(nEventLimit - events.size()));
+  }
+
+  if (changeCollection) {
+    SensorsHidlEnvironment::Instance()->setCollection(false);
+  }
+  return events;
+}
+
+bool SensorsHidlTest::typeMatchStringType(SensorType type, const hidl_string& stringType) {
+
+  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+    return true;
+  }
+
+  bool res = true;
+  switch (type) {
+#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
+    case SensorType::type: res = stringType == SENSOR_STRING_TYPE_ ## type;\
+      break;\
+
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
+    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
+    default:
+      ALOGW("Type %d is not checked, stringType = %s", (int)type, stringType.c_str());
+#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
+  }
+  return res;
+}
+
+bool SensorsHidlTest::typeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
+  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+    return true;
+  }
+
+  SensorFlagBits expected = expectedReportModeForType(type);
+
+  return expected == (SensorFlagBits)-1 || expected == reportMode;
+}
+
+bool SensorsHidlTest::delayMatchReportMode(
+    int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode) {
+  bool res = true;
+  switch(reportMode) {
+    case SensorFlagBits::CONTINUOUS_MODE:
+      res = (minDelay > 0) && (maxDelay >= 0);
+      break;
+    case SensorFlagBits::ON_CHANGE_MODE:
+      //TODO: current implementation does not satisfy minDelay == 0 on Proximity
+      res = (minDelay >= 0) && (maxDelay >= 0);
+      //res = (minDelay == 0) && (maxDelay >= 0);
+      break;
+    case SensorFlagBits::ONE_SHOT_MODE:
+      res = (minDelay == -1) && (maxDelay == 0);
+      break;
+    case SensorFlagBits::SPECIAL_REPORTING_MODE:
+      res = (minDelay == 0) && (maxDelay == 0);
+      break;
+    default:
+      res = false;
+  }
+
+  return res;
+}
+
+SensorFlagBits SensorsHidlTest::expectedReportModeForType(SensorType type) {
+  switch (type) {
+    case SensorType::ACCELEROMETER:
+    case SensorType::GYROSCOPE:
+    case SensorType::MAGNETIC_FIELD:
+    case SensorType::ORIENTATION:
+    case SensorType::PRESSURE:
+    case SensorType::TEMPERATURE:
+    case SensorType::GRAVITY:
+    case SensorType::LINEAR_ACCELERATION:
+    case SensorType::ROTATION_VECTOR:
+    case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+    case SensorType::GAME_ROTATION_VECTOR:
+    case SensorType::GYROSCOPE_UNCALIBRATED:
+    case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+    case SensorType::POSE_6DOF:
+    case SensorType::HEART_BEAT:
+      return SensorFlagBits::CONTINUOUS_MODE;
+
+    case SensorType::LIGHT:
+    case SensorType::PROXIMITY:
+    case SensorType::RELATIVE_HUMIDITY:
+    case SensorType::AMBIENT_TEMPERATURE:
+    case SensorType::HEART_RATE:
+    case SensorType::DEVICE_ORIENTATION:
+    case SensorType::MOTION_DETECT:
+    case SensorType::STEP_COUNTER:
+      return SensorFlagBits::ON_CHANGE_MODE;
+
+    case SensorType::SIGNIFICANT_MOTION:
+    case SensorType::WAKE_GESTURE:
+    case SensorType::GLANCE_GESTURE:
+    case SensorType::PICK_UP_GESTURE:
+      return SensorFlagBits::ONE_SHOT_MODE;
+
+    case SensorType::STEP_DETECTOR:
+    case SensorType::TILT_DETECTOR:
+    case SensorType::WRIST_TILT_GESTURE:
+    case SensorType::DYNAMIC_SENSOR_META:
+      return SensorFlagBits::SPECIAL_REPORTING_MODE;
+
+    default:
+      ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
+      return (SensorFlagBits)-1;
+  }
+}
+
+SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
+  SensorInfo ret;
+
+  ret.type = (SensorType) -1;
+  S()->getSensorsList(
+      [&] (const auto &list) {
+        const size_t count = list.size();
+        for (size_t i = 0; i < count; ++i) {
+          if (list[i].type == type) {
+            ret = list[i];
+            return;
+          }
+        }
+      });
+
+  return ret;
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, SensorListValid) {
+  S()->getSensorsList(
+      [&] (const auto &list) {
+        const size_t count = list.size();
+        for (size_t i = 0; i < count; ++i) {
+          auto &s = list[i];
+          ALOGV("\t%zu: handle=%#08x type=%d name=%s",
+                i, s.sensorHandle, (int)s.type, s.name.c_str());
+
+          // Test non-empty type string
+          ASSERT_FALSE(s.typeAsString.empty());
+
+          // Test defined type matches defined string type
+          ASSERT_TRUE(typeMatchStringType(s.type, s.typeAsString));
+
+          // Test if all sensor has name and vendor
+          ASSERT_FALSE(s.name.empty());
+          ASSERT_FALSE(s.vendor.empty());
+
+          // Test power > 0, maxRange > 0
+          ASSERT_GE(s.power, 0);
+          ASSERT_GT(s.maxRange, 0);
+
+          // Info type, should have no sensor
+          ASSERT_FALSE(
+              s.type == SensorType::ADDITIONAL_INFO
+              || s.type == SensorType::META_DATA);
+
+          // Test fifoMax >= fifoReserved
+          ALOGV("max reserve = %d, %d", s.fifoMaxEventCount, s.fifoReservedEventCount);
+          ASSERT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount);
+
+          // Test Reporting mode valid
+          ASSERT_TRUE(typeMatchReportMode(s.type, extractReportMode(s.flags)));
+
+          // Test min max are in the right order
+          ASSERT_LE(s.minDelay, s.maxDelay);
+          // Test min/max delay matches reporting mode
+          ASSERT_TRUE(delayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
+        }
+      });
+}
+
+// Test if sensor hal can do normal accelerometer streaming properly
+TEST_F(SensorsHidlTest, NormalAccelerometerStreamingOperation) {
+
+  std::vector<Event> events;
+
+  constexpr int64_t samplingPeriodInNs = 20ull*1000*1000; // 20ms
+  constexpr int64_t batchingPeriodInNs = 0; // no batching
+  constexpr useconds_t minTimeUs = 5*1000*1000;  // 5 s
+  constexpr size_t minNEvent = 100;  // at lease 100 events
+  constexpr SensorType type = SensorType::ACCELEROMETER;
+
+  SensorInfo sensor = defaultSensorByType(type);
+
+  if (!isValidType(sensor.type)) {
+    // no default sensor of this type
+    return;
+  }
+
+  int32_t handle = sensor.sensorHandle;
+
+  ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
+  ASSERT_EQ(activate(handle, 1), Result::OK);
+  events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
+  ASSERT_EQ(activate(handle, 0), Result::OK);
+
+  ALOGI("Collected %zu samples", events.size());
+
+  ASSERT_GT(events.size(), 0);
+
+  size_t nRealEvent = 0;
+  for (auto & e : events) {
+    if (e.sensorType == type) {
+
+      ASSERT_EQ(e.sensorHandle, handle);
+
+      Vec3 acc = e.u.vec3;
+
+      double gravityNorm = std::sqrt(acc.x * acc.x + acc.y * acc.y + acc.z * acc.z);
+      ALOGV("Norm = %f", gravityNorm);
+
+      // assert this is earth gravity
+      ASSERT_TRUE(std::fabs(gravityNorm - GRAVITY_EARTH) < 1);
+
+      ++ nRealEvent;
+    } else {
+      ALOGI("Event type %d, handle %d", (int) e.sensorType, (int) e.sensorHandle);
+      // Only meta types are allowed besides the subscribed sensor
+      ASSERT_TRUE(isMetaSensorType(e.sensorType));
+    }
+  }
+
+  ASSERT_GE(nRealEvent, minNEvent / 2); // make sure returned events are not all meta
+}
+
+// Test if sensor hal can do gyroscope streaming properly
+TEST_F(SensorsHidlTest, NormalGyroscopeStreamingOperation) {
+  std::vector<Event> events;
+
+  constexpr int64_t samplingPeriodInNs = 10ull*1000*1000; // 10ms
+  constexpr int64_t batchingPeriodInNs = 0; // no batching
+  constexpr useconds_t minTimeUs = 5*1000*1000;  // 5 s
+  constexpr size_t minNEvent = 200;
+  constexpr SensorType type = SensorType::GYROSCOPE;
+
+  SensorInfo sensor = defaultSensorByType(type);
+
+  if (!isValidType(sensor.type)) {
+    // no default sensor of this type
+    return;
+  }
+
+  int32_t handle = sensor.sensorHandle;
+
+  ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
+  ASSERT_EQ(activate(handle, 1), Result::OK);
+  events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
+  ASSERT_EQ(activate(handle, 0), Result::OK);
+
+  ALOGI("Collected %zu samples", events.size());
+
+  ASSERT_GT(events.size(), 0u);
+
+  size_t nRealEvent = 0;
+  for (auto & e : events) {
+    if (e.sensorType == type) {
+
+      ASSERT_EQ(e.sensorHandle, handle);
+
+      Vec3 gyro = e.u.vec3;
+
+      double gyroNorm = std::sqrt(gyro.x * gyro.x + gyro.y * gyro.y + gyro.z * gyro.z);
+      ALOGV("Gyro Norm = %f", gyroNorm);
+
+      // assert not drifting
+      ASSERT_TRUE(gyroNorm < 0.1);  // < ~5 degree/s
+
+      ++ nRealEvent;
+    } else {
+      ALOGI("Event type %d, handle %d", (int) e.sensorType, (int) e.sensorHandle);
+      // Only meta types are allowed besides the subscribed sensor
+      ASSERT_TRUE(isMetaSensorType(e.sensorType));
+    }
+  }
+
+  ASSERT_GE(nRealEvent, minNEvent / 2); // make sure returned events are not all meta
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+  std::vector<Event> events1, events2;
+
+  constexpr int64_t batchingPeriodInNs = 0; // no batching
+  constexpr useconds_t minTimeUs = 5*1000*1000;  // 5 s
+  constexpr size_t minNEvent = 50;
+  constexpr SensorType type = SensorType::ACCELEROMETER;
+
+  SensorInfo sensor = defaultSensorByType(type);
+
+  if (!isValidType(sensor.type)) {
+    // no default sensor of this type
+    return;
+  }
+
+  int32_t handle = sensor.sensorHandle;
+  int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+  int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
+
+  if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
+    // only support single rate
+    return;
+  }
+
+  ASSERT_EQ(batch(handle, minSamplingPeriodInNs, batchingPeriodInNs), Result::OK);
+  ASSERT_EQ(activate(handle, 1), Result::OK);
+
+  usleep(500000); // sleep 0.5 sec to wait for change rate to happen
+  events1 = collectEvents(sensor.minDelay * minNEvent, minNEvent, true /*clearBeforeStart*/);
+
+  ASSERT_EQ(batch(handle, maxSamplingPeriodInNs, batchingPeriodInNs), Result::OK);
+
+  usleep(500000); // sleep 0.5 sec to wait for change rate to happen
+  events2 = collectEvents(sensor.maxDelay * minNEvent, minNEvent, true /*clearBeforeStart*/);
+
+  ASSERT_EQ(activate(handle, 0), Result::OK);
+
+  ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
+
+  ASSERT_GT(events1.size(), 0u);
+  ASSERT_GT(events2.size(), 0u);
+
+  int64_t minDelayAverageInterval, maxDelayAverageInterval;
+
+  size_t nEvent = 0;
+  int64_t prevTimestamp = -1;
+  int64_t timestampInterval = 0;
+  for (auto & e : events1) {
+    if (e.sensorType == type) {
+      ASSERT_EQ(e.sensorHandle, handle);
+      if (prevTimestamp > 0) {
+        timestampInterval += e.timestamp - prevTimestamp;
+      }
+      prevTimestamp = e.timestamp;
+      ++ nEvent;
+    }
+  }
+  ASSERT_GT(nEvent, 2);
+  minDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+  nEvent = 0;
+  prevTimestamp = -1;
+  timestampInterval = 0;
+  for (auto & e : events2) {
+    if (e.sensorType == type) {
+      ASSERT_EQ(e.sensorHandle, handle);
+      if (prevTimestamp > 0) {
+        timestampInterval += e.timestamp - prevTimestamp;
+      }
+      prevTimestamp = e.timestamp;
+      ++ nEvent;
+    }
+  }
+  ASSERT_GT(nEvent, 2);
+  maxDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+  // change of rate is significant.
+  ASSERT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
+
+  // fastest rate sampling time is close to spec
+  ALOGI("minDelayAverageInterval = %" PRId64, minDelayAverageInterval);
+  ASSERT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+      minSamplingPeriodInNs / 10);
+}
+
+// Test if sensor hal can do normal accelerometer batching properly
+TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
+  std::vector<Event> events;
+
+  constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
+  constexpr useconds_t minTimeUs = 5*1000*1000;  // 5 s
+  constexpr size_t minNEvent = 50;
+  constexpr SensorType type = SensorType::ACCELEROMETER;
+  constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
+
+  SensorInfo sensor = defaultSensorByType(type);
+
+  if (!isValidType(sensor.type)) {
+    // no default sensor of this type
+    return;
+  }
+
+  int32_t handle = sensor.sensorHandle;
+  int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+  uint32_t minFifoCount = sensor.fifoReservedEventCount;
+  int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
+
+  if (batchingPeriodInNs < oneSecondInNs) {
+    // batching size too small to test reliably
+    return;
+  }
+
+  batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
+
+  ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
+
+  int64_t allowedBatchDeliverTimeNs =
+      std::max(oneSecondInNs, batchingPeriodInNs / 10);
+
+  ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
+  ASSERT_EQ(activate(handle, 1), Result::OK);
+
+  usleep(500000); // sleep 0.5 sec to wait for initialization
+  ASSERT_EQ(flush(handle), Result::OK);
+
+  // wait for 80% of the reserved batching period
+  // there should not be any significant amount of events
+  // since collection is not enabled all events will go down the drain
+  usleep(batchingPeriodInNs / 1000 * 8 / 10);
+
+  SensorsHidlEnvironment::Instance()->setCollection(true);
+  // 0.8 + 0.3 times the batching period
+  // plus some time for the event to deliver
+  events = collectEvents(
+      batchingPeriodInNs / 1000 * 3 / 10,
+        minFifoCount, true /*clearBeforeStart*/, false /*change collection*/);
+
+  ASSERT_EQ(flush(handle), Result::OK);
+
+  events = collectEvents(allowedBatchDeliverTimeNs / 1000,
+        minFifoCount, true /*clearBeforeStart*/, false /*change collection*/);
+
+  SensorsHidlEnvironment::Instance()->setCollection(false);
+  ASSERT_EQ(activate(handle, 0), Result::OK);
+
+  size_t nEvent = 0;
+  for (auto & e : events) {
+    if (e.sensorType == type && e.sensorHandle == handle) {
+      ++ nEvent;
+    }
+  }
+
+  // at least reach 90% of advertised capacity
+  ASSERT_GT(nEvent, (size_t)(batchingPeriodInNs / minSamplingPeriodInNs * 9 / 10));
+}
+
+// Test sensor event direct report with ashmem for gyro sensor
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReport) {
+
+  constexpr SensorType type = SensorType::GYROSCOPE;
+  constexpr size_t kEventSize = 104;
+  constexpr size_t kNEvent = 500;
+  constexpr size_t kMemSize = kEventSize * kNEvent;
+
+  SensorInfo sensor = defaultSensorByType(type);
+
+  if (!(sensor.flags | SensorFlagBits::MASK_DIRECT_REPORT)
+      || !(sensor.flags | SensorFlagBits::DIRECT_CHANNEL_ASHMEM)) {
+    // does not declare support
+    return;
+  }
+
+  std::unique_ptr<SensorsTestSharedMemory>
+      mem(SensorsTestSharedMemory::create(SharedMemType::ASHMEM, kMemSize));
+  ASSERT_NE(mem, nullptr);
+
+  char* buffer = mem->getBuffer();
+  // fill memory with data
+  for (size_t i = 0; i < kMemSize; ++i) {
+    buffer[i] = '\xcc';
+  }
+
+  int32_t channelHandle;
+  registerDirectChannel(mem->getSharedMemInfo(),
+      [&channelHandle] (auto result, auto channelHandle_) {
+          ASSERT_EQ(result, Result::OK);
+          channelHandle = channelHandle_;
+      });
+
+  // check memory is zeroed
+  for (size_t i = 0; i < kMemSize; ++i) {
+    ASSERT_EQ(buffer[i], '\0');
+  }
+
+  int32_t eventToken;
+  configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::NORMAL,
+      [&eventToken] (auto result, auto token) {
+          ASSERT_EQ(result, Result::OK);
+          eventToken = token;
+      });
+
+  usleep(1500000); // sleep 1 sec for data, plus 0.5 sec for initialization
+  auto events = mem->parseEvents();
+
+  // allowed to be 55% of nominal freq (50Hz)
+  ASSERT_GT(events.size(), 50 / 2);
+  ASSERT_LT(events.size(), static_cast<size_t>(110*1.5));
+
+  int64_t lastTimestamp = 0;
+  for (auto &e : events) {
+    ASSERT_EQ(e.sensorType, type);
+    ASSERT_EQ(e.sensorHandle, eventToken);
+    ASSERT_GT(e.timestamp, lastTimestamp);
+
+    Vec3 gyro = e.u.vec3;
+    double gyroNorm = std::sqrt(gyro.x * gyro.x + gyro.y * gyro.y + gyro.z * gyro.z);
+    // assert not drifting
+    ASSERT_TRUE(gyroNorm < 0.1);  // < ~5 degree/sa
+
+    lastTimestamp = e.timestamp;
+  }
+
+  // stop sensor and unregister channel
+  configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
+        [&eventToken] (auto result, auto) {
+            ASSERT_EQ(result, Result::OK);
+        });
+  ASSERT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
+}
+
+int main(int argc, char **argv) {
+  ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
+// vim: set ts=2 sw=2
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/__init__.py b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/__init__.py
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/Android.mk b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/__init__.py b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/__init__.py
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/Android.mk b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/Android.mk
new file mode 100644
index 0000000..79f8f7a
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SensorsHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/sensors/hidl/host
+include test/vts/tools/build/Android.host_config.mk
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/AndroidTest.xml b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..6e40610
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL sensors test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/sensors/1.0/vts/Sensors.vts->/data/local/tmp/spec/Sensors.vts" />
+        <option name="push" value="spec/hardware/interfaces/sensors/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="SensorsHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/sensors/hidl/host/SensorsHidlTest" />
+        <option name="test-timeout" value="3m" />
+    </test>
+</configuration>
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py
new file mode 100644
index 0000000..3c7fbbb
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/SensorsHidlTest.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python3.4
+#
+# 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.
+#
+
+import logging
+import time
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.profiling import profiling_utils
+
+
+class SensorsHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """Host testcase class for the SENSORS HIDL HAL.
+
+    This class set-up/tear-down the webDB host test framwork and contains host test cases for
+    sensors HIDL HAL.
+    """
+
+    def setUpClass(self):
+        """Creates a mirror and turns on the framework-layer SENSORS service."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        # Test using the binderized mode
+        self.dut.shell.one.Execute(
+            "setprop vts.hal.vts.hidl.get_stub true")
+
+        self.dut.hal.InitHidlHal(
+            target_type="sensors",
+            target_basepaths=self.dut.libPaths,
+            target_version=1.0,
+            target_package="android.hardware.sensors",
+            target_component_name="ISensors",
+            hw_binder_service_name=None,
+            bits=64 if self.dut.is64Bit else 32)
+
+    def tearDownClass(self):
+        """ If profiling is enabled for the test, collect the profiling data
+            and disable profiling after the test is done.
+        """
+        if self.enable_profiling:
+            self.ProcessAndUploadTraceData()
+
+    def setUpTest(self):
+        if self.enable_profiling:
+            profiling_utils.EnableVTSProfiling(self.dut.shell.one)
+
+    def tearDownTest(self):
+        if self.enable_profiling:
+            profiling_trace_path = getattr(
+                self, self.VTS_PROFILING_TRACING_PATH, "")
+            self.ProcessTraceDataForTestCase(self.dut, profiling_trace_path)
+            profiling_utils.DisableVTSProfiling(self.dut.shell.one)
+
+    def testSensorsBasic(self):
+        """Test the basic operation of test framework and sensor HIDL HAL
+
+        This test obtains predefined enum values via sensors HIDL HAL host test framework and
+        compares them to known values as a sanity check to make sure both sensors HAL
+        and the test framework are working properly.
+        """
+        sensors_types = self.dut.hal.sensors.GetHidlTypeInterface("types")
+        logging.info("sensors_types: %s", sensors_types)
+        logging.info("OK: %s", sensors_types.OK)
+        logging.info("BAD_VALUE: %s", sensors_types.BAD_VALUE)
+        logging.info("PERMISSION_DENIED: %s", sensors_types.PERMISSION_DENIED)
+        logging.info("INVALID_OPERATION: %s", sensors_types.INVALID_OPERATION)
+        asserts.assertEqual(sensors_types.OK, 0);
+        asserts.assertEqual(sensors_types.BAD_VALUE, -22);
+
+        logging.info("sensor types:")
+        logging.info("SENSOR_TYPE_ACCELEROMETER: %s", sensors_types.SENSOR_TYPE_ACCELEROMETER)
+        logging.info("SENSOR_TYPE_GEOMAGNETIC_FIELD: %s", sensors_types.SENSOR_TYPE_GEOMAGNETIC_FIELD)
+        logging.info("SENSOR_TYPE_GYROSCOPE: %s", sensors_types.SENSOR_TYPE_GYROSCOPE)
+        asserts.assertEqual(sensors_types.SENSOR_TYPE_ACCELEROMETER, 1);
+        asserts.assertEqual(sensors_types.SENSOR_TYPE_GEOMAGNETIC_FIELD, 2);
+        asserts.assertEqual(sensors_types.SENSOR_TYPE_GYROSCOPE, 4);
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/__init__.py b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host/__init__.py
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/Android.mk b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/Android.mk
new file mode 100644
index 0000000..6029cc0
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SensorsHidlProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/sensors/hidl/host_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/AndroidTest.xml b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/AndroidTest.xml
new file mode 100644
index 0000000..c056d90
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/host_profiling/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL sensors test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/sensors/1.0/vts/Sensors.vts->/data/local/tmp/spec/Sensors.vts" />
+        <option name="push" value="spec/hardware/interfaces/sensors/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="SensorsHidlProfilingTest" />
+        <option name="test-case-path" value="vts/testcases/hal/sensors/hidl/host/SensorsHidlTest" />
+        <option name="test-timeout" value="3m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/Android.mk b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/Android.mk
new file mode 100644
index 0000000..c71a661
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SensorsHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/sensors/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/AndroidTest.xml b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..6329d5d
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS sensors HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="SensorsHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/sensors_hidl_hal_test/sensors_hidl_hal_test,
+            _64bit::DATA/nativetest64/sensors_hidl_hal_test/sensors_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-disable-framework" value="true" />
+        <option name="test-timeout" value="10m" />
+    </test>
+</configuration>
+
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/Android.mk b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..1b81381
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := SensorsHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/sensors/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/AndroidTest.xml b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..80e46b7
--- /dev/null
+++ b/sensors/1.0/vts/functional/vts/testcases/hal/sensors/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS sensors HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="SensorsHidlTargetProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/sensors_hidl_hal_test/sensors_hidl_hal_test,
+            _64bit::DATA/nativetest64/sensors_hidl_hal_test/sensors_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="binary-test-disable-framework" value="true" />
+        <option name="test-timeout" value="10m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
+
diff --git a/sensors/1.0/vts/types.vts b/sensors/1.0/vts/types.vts
new file mode 100644
index 0000000..1b48916
--- /dev/null
+++ b/sensors/1.0/vts/types.vts
@@ -0,0 +1,900 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.sensors"
+
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::Result"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "PERMISSION_DENIED"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "NO_MEMORY"
+        scalar_value: {
+            int32_t: -12
+        }
+        enumerator: "BAD_VALUE"
+        scalar_value: {
+            int32_t: -22
+        }
+        enumerator: "INVALID_OPERATION"
+        scalar_value: {
+            int32_t: -38
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::OperationMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DATA_INJECTION"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "META_DATA"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ACCELEROMETER"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MAGNETIC_FIELD"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ORIENTATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "GYROSCOPE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "LIGHT"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "PRESSURE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "TEMPERATURE"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "PROXIMITY"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "GRAVITY"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "LINEAR_ACCELERATION"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "ROTATION_VECTOR"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "RELATIVE_HUMIDITY"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "AMBIENT_TEMPERATURE"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "MAGNETIC_FIELD_UNCALIBRATED"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "GAME_ROTATION_VECTOR"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "GYROSCOPE_UNCALIBRATED"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "SIGNIFICANT_MOTION"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "STEP_DETECTOR"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "STEP_COUNTER"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "GEOMAGNETIC_ROTATION_VECTOR"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "HEART_RATE"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "TILT_DETECTOR"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "WAKE_GESTURE"
+        scalar_value: {
+            int32_t: 23
+        }
+        enumerator: "GLANCE_GESTURE"
+        scalar_value: {
+            int32_t: 24
+        }
+        enumerator: "PICK_UP_GESTURE"
+        scalar_value: {
+            int32_t: 25
+        }
+        enumerator: "WRIST_TILT_GESTURE"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "DEVICE_ORIENTATION"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "POSE_6DOF"
+        scalar_value: {
+            int32_t: 28
+        }
+        enumerator: "STATIONARY_DETECT"
+        scalar_value: {
+            int32_t: 29
+        }
+        enumerator: "MOTION_DETECT"
+        scalar_value: {
+            int32_t: 30
+        }
+        enumerator: "HEART_BEAT"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "DYNAMIC_SENSOR_META"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "ADDITIONAL_INFO"
+        scalar_value: {
+            int32_t: 33
+        }
+        enumerator: "LOW_LATENCY_OFFBODY_DETECT"
+        scalar_value: {
+            int32_t: 34
+        }
+        enumerator: "ACCELEROMETER_UNCALIBRATED"
+        scalar_value: {
+            int32_t: 35
+        }
+        enumerator: "DEVICE_PRIVATE_BASE"
+        scalar_value: {
+            int32_t: 65536
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorFlagBits"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "WAKE_UP"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "CONTINUOUS_MODE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "ON_CHANGE_MODE"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "ONE_SHOT_MODE"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "SPECIAL_REPORTING_MODE"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "DATA_INJECTION"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "DYNAMIC_SENSOR"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "ADDITIONAL_INFO"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "DIRECT_CHANNEL_ASHMEM"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "DIRECT_CHANNEL_GRALLOC"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "MASK_REPORTING_MODE"
+        scalar_value: {
+            uint32_t: 14
+        }
+        enumerator: "MASK_DIRECT_REPORT"
+        scalar_value: {
+            uint32_t: 896
+        }
+        enumerator: "MASK_DIRECT_CHANNEL"
+        scalar_value: {
+            uint32_t: 3072
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorFlagShift"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint8_t"
+
+        enumerator: "REPORTING_MODE"
+        scalar_value: {
+            uint8_t: 1
+        }
+        enumerator: "DATA_INJECTION"
+        scalar_value: {
+            uint8_t: 4
+        }
+        enumerator: "DYNAMIC_SENSOR"
+        scalar_value: {
+            uint8_t: 5
+        }
+        enumerator: "ADDITIONAL_INFO"
+        scalar_value: {
+            uint8_t: 6
+        }
+        enumerator: "DIRECT_REPORT"
+        scalar_value: {
+            uint8_t: 7
+        }
+        enumerator: "DIRECT_CHANNEL"
+        scalar_value: {
+            uint8_t: 10
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sensorHandle"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "vendor"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "version"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SensorType"
+    }
+    struct_value: {
+        name: "typeAsString"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "maxRange"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "resolution"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "power"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "minDelay"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "fifoReservedEventCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "fifoMaxEventCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "requiredPermission"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "maxDelay"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_MASK
+        predefined_type: "::android::hardware::sensors::V1_0::SensorFlagBits"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int8_t"
+
+        enumerator: "NO_CONTACT"
+        scalar_value: {
+            int8_t: -1
+        }
+        enumerator: "UNRELIABLE"
+        scalar_value: {
+            int8_t: 0
+        }
+        enumerator: "ACCURACY_LOW"
+        scalar_value: {
+            int8_t: 1
+        }
+        enumerator: "ACCURACY_MEDIUM"
+        scalar_value: {
+            int8_t: 2
+        }
+        enumerator: "ACCURACY_HIGH"
+        scalar_value: {
+            int8_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::Vec3"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "x"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "y"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "z"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SensorStatus"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::Vec4"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "x"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "y"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "z"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "w"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::Uncal"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "x"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "y"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "z"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "x_bias"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "y_bias"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "z_bias"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::HeartRate"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "bpm"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "status"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SensorStatus"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::MetaDataEventType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "META_DATA_FLUSH_COMPLETE"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::MetaData"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "what"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::MetaDataEventType"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::DynamicSensorInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "connected"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "sensorHandle"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "uuid"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 16
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::AdditionalInfoType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "AINFO_BEGIN"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "AINFO_END"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "AINFO_UNTRACKED_DELAY"
+        scalar_value: {
+            uint32_t: 65536
+        }
+        enumerator: "AINFO_INTERNAL_TEMPERATURE"
+        scalar_value: {
+            uint32_t: 65537
+        }
+        enumerator: "AINFO_VEC3_CALIBRATION"
+        scalar_value: {
+            uint32_t: 65538
+        }
+        enumerator: "AINFO_SENSOR_PLACEMENT"
+        scalar_value: {
+            uint32_t: 65539
+        }
+        enumerator: "AINFO_SAMPLING"
+        scalar_value: {
+            uint32_t: 65540
+        }
+        enumerator: "AINFO_CHANNEL_NOISE"
+        scalar_value: {
+            uint32_t: 131072
+        }
+        enumerator: "AINFO_CHANNEL_SAMPLER"
+        scalar_value: {
+            uint32_t: 131073
+        }
+        enumerator: "AINFO_CHANNEL_FILTER"
+        scalar_value: {
+            uint32_t: 131074
+        }
+        enumerator: "AINFO_CHANNEL_LINEAR_TRANSFORM"
+        scalar_value: {
+            uint32_t: 131075
+        }
+        enumerator: "AINFO_CHANNEL_NONLINEAR_MAP"
+        scalar_value: {
+            uint32_t: 131076
+        }
+        enumerator: "AINFO_CHANNEL_RESAMPLER"
+        scalar_value: {
+            uint32_t: 131077
+        }
+        enumerator: "AINFO_LOCAL_GEOMAGNETIC_FIELD"
+        scalar_value: {
+            uint32_t: 196608
+        }
+        enumerator: "AINFO_LOCAL_GRAVITY"
+        scalar_value: {
+            uint32_t: 196609
+        }
+        enumerator: "AINFO_DOCK_STATE"
+        scalar_value: {
+            uint32_t: 196610
+        }
+        enumerator: "AINFO_HIGH_PERFORMANCE_MODE"
+        scalar_value: {
+            uint32_t: 196611
+        }
+        enumerator: "AINFO_MAGNETIC_FIELD_CALIBRATION"
+        scalar_value: {
+            uint32_t: 196612
+        }
+        enumerator: "AINFO_CUSTOM_START"
+        scalar_value: {
+            uint32_t: 268435456
+        }
+        enumerator: "AINFO_DEBUGGING_START"
+        scalar_value: {
+            uint32_t: 1073741824
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::AdditionalInfo"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::sensors::V1_0::AdditionalInfo::Payload"
+        type: TYPE_UNION
+        union_value: {
+            name: "data_int32"
+            type: TYPE_ARRAY
+            vector_value: {
+                vector_size: 14
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+        }
+        union_value: {
+            name: "data_float"
+            type: TYPE_ARRAY
+            vector_value: {
+                vector_size: 14
+                type: TYPE_SCALAR
+                scalar_type: "float_t"
+            }
+        }
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::AdditionalInfoType"
+    }
+    struct_value: {
+        name: "serial"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "u"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::sensors::V1_0::AdditionalInfo::Payload"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::EventPayload"
+    type: TYPE_UNION
+    union_value: {
+        name: "vec3"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::Vec3"
+    }
+    union_value: {
+        name: "vec4"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::Vec4"
+    }
+    union_value: {
+        name: "uncal"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::Uncal"
+    }
+    union_value: {
+        name: "meta"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::MetaData"
+    }
+    union_value: {
+        name: "scalar"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    union_value: {
+        name: "stepCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    union_value: {
+        name: "heartRate"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::HeartRate"
+    }
+    union_value: {
+        name: "pose6DOF"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 15
+            type: TYPE_SCALAR
+            scalar_type: "float_t"
+        }
+    }
+    union_value: {
+        name: "dynamic"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::DynamicSensorInfo"
+    }
+    union_value: {
+        name: "additional"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::sensors::V1_0::AdditionalInfo"
+    }
+    union_value: {
+        name: "data"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 16
+            type: TYPE_SCALAR
+            scalar_type: "float_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::Event"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "timestamp"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "sensorHandle"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "sensorType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SensorType"
+    }
+    struct_value: {
+        name: "u"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::sensors::V1_0::EventPayload"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::RateLevel"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STOP"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "FAST"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VERY_FAST"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SharedMemType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ASHMEM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "GRALLOC"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SharedMemFormat"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SENSORS_EVENT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SensorsEventFormatOffset"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint16_t"
+
+        enumerator: "SIZE_FIELD"
+        scalar_value: {
+            uint16_t: 0
+        }
+        enumerator: "REPORT_TOKEN"
+        scalar_value: {
+            uint16_t: 4
+        }
+        enumerator: "SENSOR_TYPE"
+        scalar_value: {
+            uint16_t: 8
+        }
+        enumerator: "ATOMIC_COUNTER"
+        scalar_value: {
+            uint16_t: 12
+        }
+        enumerator: "TIMESTAMP"
+        scalar_value: {
+            uint16_t: 16
+        }
+        enumerator: "DATA"
+        scalar_value: {
+            uint16_t: 24
+        }
+        enumerator: "RESERVED"
+        scalar_value: {
+            uint16_t: 88
+        }
+        enumerator: "TOTAL_LENGTH"
+        scalar_value: {
+            uint16_t: 104
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::sensors::V1_0::SharedMemInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SharedMemType"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::sensors::V1_0::SharedMemFormat"
+    }
+    struct_value: {
+        name: "size"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "memoryHandle"
+        type: TYPE_HANDLE
+    }
+}
+
diff --git a/sensors/Android.bp b/sensors/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/sensors/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/soundtrigger/2.0/Android.bp b/soundtrigger/2.0/Android.bp
new file mode 100644
index 0000000..5b50f39
--- /dev/null
+++ b/soundtrigger/2.0/Android.bp
@@ -0,0 +1,222 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0",
+    srcs: [
+        "types.hal",
+        "ISoundTriggerHw.hal",
+        "ISoundTriggerHwCallback.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/types.cpp",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwAll.cpp",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0",
+    srcs: [
+        "types.hal",
+        "ISoundTriggerHw.hal",
+        "ISoundTriggerHwCallback.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/types.h",
+        "android/hardware/soundtrigger/2.0/ISoundTriggerHw.h",
+        "android/hardware/soundtrigger/2.0/IHwSoundTriggerHw.h",
+        "android/hardware/soundtrigger/2.0/BnHwSoundTriggerHw.h",
+        "android/hardware/soundtrigger/2.0/BpHwSoundTriggerHw.h",
+        "android/hardware/soundtrigger/2.0/BsSoundTriggerHw.h",
+        "android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h",
+        "android/hardware/soundtrigger/2.0/IHwSoundTriggerHwCallback.h",
+        "android/hardware/soundtrigger/2.0/BnHwSoundTriggerHwCallback.h",
+        "android/hardware/soundtrigger/2.0/BpHwSoundTriggerHwCallback.h",
+        "android/hardware/soundtrigger/2.0/BsSoundTriggerHwCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.soundtrigger@2.0",
+    generated_sources: ["android.hardware.soundtrigger@2.0_genc++"],
+    generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger.vts.driver@2.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "types.hal",
+        "ISoundTriggerHw.hal",
+        "ISoundTriggerHwCallback.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/types.vts.cpp",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHw.vts.cpp",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger.vts.driver@2.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "types.hal",
+        "ISoundTriggerHw.hal",
+        "ISoundTriggerHwCallback.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/types.vts.h",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHw.vts.h",
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.soundtrigger.vts.driver@2.0",
+    generated_sources: ["android.hardware.soundtrigger.vts.driver@2.0_genc++"],
+    generated_headers: ["android.hardware.soundtrigger.vts.driver@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.soundtrigger.vts.driver@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.soundtrigger@2.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "ISoundTriggerHw.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/SoundTriggerHw.vts.cpp",
+        "android/hardware/soundtrigger/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "ISoundTriggerHw.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/SoundTriggerHw.vts.h",
+        "android/hardware/soundtrigger/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler",
+    generated_sources: ["android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.soundtrigger@2.0-ISoundTriggerHw-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.soundtrigger@2.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "ISoundTriggerHwCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwCallback.vts.cpp",
+        "android/hardware/soundtrigger/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.soundtrigger@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/soundtrigger/2.0/ $(genDir)/android/hardware/soundtrigger/2.0/",
+    srcs: [
+        "ISoundTriggerHwCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/soundtrigger/2.0/SoundTriggerHwCallback.vts.h",
+        "android/hardware/soundtrigger/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler",
+    generated_sources: ["android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.soundtrigger@2.0-ISoundTriggerHwCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.soundtrigger@2.0",
+    ],
+}
diff --git a/soundtrigger/2.0/Android.mk b/soundtrigger/2.0/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/ISoundTriggerHw.hal b/soundtrigger/2.0/ISoundTriggerHw.hal
new file mode 100644
index 0000000..cf35ef1
--- /dev/null
+++ b/soundtrigger/2.0/ISoundTriggerHw.hal
@@ -0,0 +1,243 @@
+/*
+ * 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.
+ */
+
+package android.hardware.soundtrigger@2.0;
+
+import android.hardware.audio.common@2.0;
+
+import ISoundTriggerHwCallback;
+
+interface ISoundTriggerHw {
+
+    /*
+     * Sound trigger implementation descriptor read by the framework via
+     * getProperties(). Used by SoundTrigger service to report to applications
+     * and manage concurrency and policy.
+     */
+    struct Properties {
+        /* Implementor name */
+        string   implementor;
+        /* Implementation description */
+        string   description;
+        /* Implementation version */
+        uint32_t version;
+        /* Unique implementation ID. The UUID must change with each version of
+           the engine implementation */
+        Uuid     uuid;
+        /* Maximum number of concurrent sound models loaded */
+        uint32_t maxSoundModels;
+        /* Maximum number of key phrases */
+        uint32_t maxKeyPhrases;
+        /* Maximum number of concurrent users detected */
+        uint32_t maxUsers;
+        /* All supported modes. e.g RecognitionMode.VOICE_TRIGGER */
+        uint32_t recognitionModes;
+        /* Supports seamless transition from detection to capture */
+        bool     captureTransition;
+        /* Maximum buffering capacity in ms if captureTransition is true */
+        uint32_t maxBufferMs;
+        /* Supports capture by other use cases while detection is active */
+        bool     concurrentCapture;
+        /* Returns the trigger capture in event */
+        bool     triggerInEvent;
+        /* Rated power consumption when detection is active with TDB
+         * silence/sound/speech ratio */
+        uint32_t powerConsumptionMw;
+    };
+
+
+    /*
+     * Base sound model descriptor. This struct is the header of a larger block
+     * passed to loadSoundModel() and contains the binary data of the
+     * sound model.
+     */
+    struct SoundModel {
+        /* Model type. e.g. SoundModelType.KEYPHRASE */
+        SoundModelType type;
+        /* Unique sound model ID. */
+        Uuid           uuid;
+        /* Unique vendor ID. Identifies the engine the sound model
+         * was build for */
+        Uuid           vendorUuid;
+        /* Opaque data transparent to Android framework */
+        vec<uint8_t>   data;
+    };
+
+    /* Key phrase descriptor */
+    struct Phrase {
+        /* Unique keyphrase ID assigned at enrollment time */
+        uint32_t      id;
+        /* Recognition modes supported by this key phrase */
+        uint32_t      recognitionModes;
+        /* List of users IDs associated with this key phrase */
+        vec<uint32_t> users;
+        /* Locale - Java Locale style (e.g. en_US) */
+        string        locale;
+        /* Phrase text in UTF-8 format. */
+        string        text;
+    };
+
+    /*
+     * Specialized sound model for key phrase detection.
+     * Proprietary representation of key phrases in binary data must match
+     * information indicated by phrases field
+     */
+    struct PhraseSoundModel {
+        /* Common part of sound model descriptor */
+        SoundModel  common;
+        /* List of descriptors for key phrases supported by this sound model */
+        vec<Phrase> phrases;
+    };
+
+    /*
+     * Configuration for sound trigger capture session passed to
+     * startRecognition() method
+     */
+    struct RecognitionConfig {
+        /* IO handle that will be used for capture. N/A if captureRequested
+         * is false */
+        AudioIoHandle   captureHandle;
+        /* Input device requested for detection capture */
+        AudioDevice     captureDevice;
+        /* Capture and buffer audio for this recognition instance */
+        bool            captureRequested;
+        /* Configuration for each key phrase */
+        vec<PhraseRecognitionExtra> phrases;
+        /* Opaque capture configuration data transparent to the framework */
+        vec<uint8_t>    data;
+    };
+
+
+    /*
+     * Retrieve implementation properties.
+     * @return retval Operation completion status: 0 in case of success,
+     *                -ENODEV in case of initialization error.
+     * @return properties A Properties structure containing implementation
+     *                    description and capabilities.
+     */
+    getProperties() generates (int32_t retval, Properties properties);
+
+    /*
+     * Load a sound model. Once loaded, recognition of this model can be
+     * started and stopped. Only one active recognition per model at a time.
+     * The SoundTrigger service must handle concurrent recognition requests by
+     * different users/applications on the same model.
+     * The implementation returns a unique handle used by other functions
+     * (unloadSoundModel(), startRecognition(), etc...
+     * @param soundModel A SoundModel structure describing the sound model to
+     *                   load.
+     * @param callback The callback interface on which the soundmodelCallback()
+     *                 method will be called upon completion.
+     * @param cookie The value of the cookie argument passed to the completion
+     *               callback. This unique context information is assigned and
+     *               used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *                -EINVAL in case of invalid sound model (e.g 0 data size),
+     *                -ENOSYS in case of invalid operation (e.g max number of
+     *                models exceeded),
+     *                -ENOMEM in case of memory allocation failure,
+     *                -ENODEV in case of initialization error.
+     * @return modelHandle A unique handle assigned by the HAL for use by the
+     *                framework when controlling activity for this sound model.
+     */
+    loadSoundModel(SoundModel soundModel,
+                   ISoundTriggerHwCallback callback,
+                   CallbackCookie cookie)
+            generates (int32_t retval, SoundModelHandle modelHandle);
+
+    /*
+     * Load a key phrase sound model. Once loaded, recognition of this model can
+     * be started and stopped. Only one active recognition per model at a time.
+     * The SoundTrigger service must handle concurrent recognition requests by
+     * different users/applications on the same model.
+     * The implementation returns a unique handle used by other functions
+     * (unloadSoundModel(), startRecognition(), etc...
+     * @param soundModel A PhraseSoundModel structure describing the sound model
+     *                   to load.
+     * @param callback The callback interface on which the soundmodelCallback()
+     *                 method will be called upon completion.
+     * @param cookie The value of the cookie argument passed to the completion
+     *               callback. This unique context information is assigned and
+     *               used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *                -EINVAL in case of invalid sound model (e.g 0 data size),
+     *                -ENOSYS in case of invalid operation (e.g max number of
+     *                models exceeded),
+     *                -ENOMEM in case of memory allocation failure,
+     *                -ENODEV in case of initialization error.
+     * @return modelHandle A unique handle assigned by the HAL for use by the
+     *                framework when controlling activity for this sound model.
+     */
+    loadPhraseSoundModel(PhraseSoundModel soundModel,
+                   ISoundTriggerHwCallback callback,
+                   CallbackCookie cookie)
+            generates (int32_t retval, SoundModelHandle modelHandle);
+
+    /*
+     * Unload a sound model. A sound model may be unloaded to make room for a
+     * new one to overcome implementation limitations.
+     * @param modelHandle the handle of the sound model to unload
+     * @return retval Operation completion status: 0 in case of success,
+     *                -ENOSYS if the model is not loaded,
+     *                -ENODEV in case of initialization error.
+     */
+    unloadSoundModel(SoundModelHandle modelHandle)
+            generates (int32_t retval);
+
+    /*
+     * Start recognition on a given model. Only one recognition active
+     * at a time per model. Once recognition succeeds of fails, the callback
+     * is called.
+     * @param modelHandle the handle of the sound model to use for recognition
+     * @param config A RecognitionConfig structure containing attributes of the
+     *               recognition to perform
+     * @param callback The callback interface on which the recognitionCallback()
+     *                 method must be called upon recognition.
+     * @param cookie The value of the cookie argument passed to the recognition
+     *               callback. This unique context information is assigned and
+     *               used only by the framework.
+     * @return retval Operation completion status: 0 in case of success,
+     *                -EINVAL in case of invalid recognition attributes,
+     *                -ENOSYS in case of invalid model handle,
+     *                -ENOMEM in case of memory allocation failure,
+     *                -ENODEV in case of initialization error.
+     */
+    startRecognition(SoundModelHandle modelHandle,
+                     RecognitionConfig config,
+                     ISoundTriggerHwCallback callback,
+                     CallbackCookie cookie)
+            generates (int32_t retval);
+
+    /*
+     * Stop recognition on a given model.
+     * The implementation must not call the recognition callback when stopped
+     * via this method.
+     * @param modelHandle The handle of the sound model to use for recognition
+     * @return retval Operation completion status: 0 in case of success,
+     *                -ENOSYS in case of invalid model handle,
+     *                -ENODEV in case of initialization error.
+     */
+    stopRecognition(SoundModelHandle modelHandle)
+            generates (int32_t retval);
+
+    /*
+     * Stop recognition on all models.
+     * @return retval Operation completion status: 0 in case of success,
+     *                -ENODEV in case of initialization error.
+     */
+    stopAllRecognitions()
+            generates (int32_t retval);
+};
diff --git a/soundtrigger/2.0/ISoundTriggerHwCallback.hal b/soundtrigger/2.0/ISoundTriggerHwCallback.hal
new file mode 100644
index 0000000..c6555f6
--- /dev/null
+++ b/soundtrigger/2.0/ISoundTriggerHwCallback.hal
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+package android.hardware.soundtrigger@2.0;
+
+import android.hardware.audio.common@2.0;
+
+interface ISoundTriggerHwCallback {
+    enum RecognitionStatus : uint32_t {
+        SUCCESS  = 0,
+        ABORT    = 1,
+        FAILURE  = 2,
+    };
+
+    enum SoundModelStatus : uint32_t {
+        UPDATED  = 0,
+    };
+
+    /*
+     * Generic recognition event sent via recognition callback
+     */
+    struct RecognitionEvent {
+        /* Recognition status e.g. SUCCESS */
+        RecognitionStatus status;
+        /* Sound model type for this event. e.g SoundModelType.TYPE_KEYPHRASE */
+        SoundModelType    type;
+        /* Handle of loaded sound model which triggered the event */
+        SoundModelHandle  model;
+        /* It is possible to capture audio from this */
+        /* utterance buffered by the implementation */
+        bool              captureAvailable;
+        /* Audio session ID. framework use */
+        int32_t           captureSession;
+        /* Delay in ms between end of model detection and start of audio
+        /* available for capture. A negative value is possible
+         * (e.g. if key phrase is also available for capture */
+        int32_t           captureDelayMs;
+        /* Duration in ms of audio captured before the start of the trigger.
+         * 0 if none. */
+        int32_t           capturePreambleMs;
+        /* The opaque data is the capture of the trigger sound */
+        bool              triggerInData;
+        /* Audio format of either the trigger in event data or to use for
+         * capture of the rest of the utterance */
+        AudioConfig       audioConfig;
+        /* Opaque event data */
+        vec<uint8_t>      data;
+    };
+
+    /*
+     * Specialized recognition event for key phrase recognitions
+     */
+    struct PhraseRecognitionEvent {
+        /* Common part of the recognition event */
+        RecognitionEvent common;
+        /* List of descriptors for each recognized key phrase */
+        vec<PhraseRecognitionExtra> phraseExtras;
+    };
+
+    /*
+     * Event sent via load sound model callback
+     */
+    struct ModelEvent {
+         /* Sound model status e.g. SoundModelStatus.UPDATED */
+        SoundModelStatus status;
+        /* Loaded sound model that triggered the event */
+        SoundModelHandle model;
+        /* Opaque event data, passed transparently by the framework */
+        vec<uint8_t>     data;
+    };
+
+    typedef int32_t CallbackCookie;
+
+    /*
+     * Callback method called by the HAL when the sound recognition triggers
+     * @param event A RecognitionEvent structure containing detailed results
+     *              of the recognition triggered
+     * @param cookie The cookie passed by the framework when recognition was
+     *               started (see ISoundtriggerHw.startRecognition()
+     */
+    recognitionCallback(RecognitionEvent event, CallbackCookie cookie);
+
+    /*
+     * Callback method called by the HAL when the sound recognition triggers
+     * for a key phrase sound model.
+     * @param event A RecognitionEvent structure containing detailed results
+     *              of the recognition triggered
+     * @param cookie The cookie passed by the framework when recognition was
+     *               started (see ISoundtriggerHw.startRecognition()
+     */
+    phraseRecognitionCallback(PhraseRecognitionEvent event,
+                              CallbackCookie cookie);
+    /*
+     * Callback method called by the HAL when the sound model loading completes
+     * @param event A ModelEvent structure containing detailed results of the
+     *              model loading operation
+     * @param cookie The cookie passed by the framework when loading was
+     *               initiated (see ISoundtriggerHw.loadSoundModel()
+     */
+    soundModelCallback(ModelEvent event, CallbackCookie cookie);
+};
diff --git a/soundtrigger/2.0/default/Android.mk b/soundtrigger/2.0/default/Android.mk
new file mode 100644
index 0000000..498c54f
--- /dev/null
+++ b/soundtrigger/2.0/default/Android.mk
@@ -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.
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.soundtrigger@2.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    SoundTriggerHalImpl.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+        libhidlbase \
+        libhidltransport \
+        liblog \
+        libhwbinder \
+        libutils \
+        libhardware \
+        android.hardware.soundtrigger@2.0 \
+        android.hardware.audio.common@2.0
+
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+
+ifeq ($(strip $(AUDIOSERVER_MULTILIB)),)
+LOCAL_MULTILIB := 32
+else
+LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
+endif
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
new file mode 100644
index 0000000..afda739
--- /dev/null
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
@@ -0,0 +1,595 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SoundTriggerHalImpl"
+//#define LOG_NDEBUG 0
+
+#include <android/log.h>
+#include "SoundTriggerHalImpl.h"
+
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_0 {
+namespace implementation {
+
+// static
+void SoundTriggerHalImpl::soundModelCallback(struct sound_trigger_model_event *halEvent,
+                                               void *cookie)
+{
+    if (halEvent == NULL) {
+        ALOGW("soundModelCallback called with NULL event");
+        return;
+    }
+    sp<SoundModelClient> client =
+            wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote();
+    if (client == 0) {
+        ALOGW("soundModelCallback called on stale client");
+        return;
+    }
+    if (halEvent->model != client->mHalHandle) {
+        ALOGW("soundModelCallback call with wrong handle %d on client with handle %d",
+              (int)halEvent->model, (int)client->mHalHandle);
+        return;
+    }
+
+    ISoundTriggerHwCallback::ModelEvent event;
+    convertSoundModelEventFromHal(&event, halEvent);
+    event.model = client->mId;
+
+    client->mCallback->soundModelCallback(event, client->mCookie);
+}
+
+// static
+void SoundTriggerHalImpl::recognitionCallback(struct sound_trigger_recognition_event *halEvent,
+                                               void *cookie)
+{
+    if (halEvent == NULL) {
+        ALOGW("recognitionCallback call NULL event");
+        return;
+    }
+    sp<SoundModelClient> client =
+            wp<SoundModelClient>(static_cast<SoundModelClient *>(cookie)).promote();
+    if (client == 0) {
+        ALOGW("soundModelCallback called on stale client");
+        return;
+    }
+
+    ISoundTriggerHwCallback::RecognitionEvent *event = convertRecognitionEventFromHal(halEvent);
+    event->model = client->mId;
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        client->mCallback->phraseRecognitionCallback(
+                *(reinterpret_cast<ISoundTriggerHwCallback::PhraseRecognitionEvent *>(event)),
+                client->mCookie);
+    } else {
+        client->mCallback->recognitionCallback(*event, client->mCookie);
+    }
+    delete event;
+}
+
+
+
+// Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
+Return<void> SoundTriggerHalImpl::getProperties(getProperties_cb _hidl_cb)
+{
+    ALOGV("getProperties() mHwDevice %p", mHwDevice);
+    int ret;
+    struct sound_trigger_properties halProperties;
+    ISoundTriggerHw::Properties properties;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    ret = mHwDevice->get_properties(mHwDevice, &halProperties);
+
+    convertPropertiesFromHal(&properties, &halProperties);
+
+    ALOGV("getProperties implementor %s recognitionModes %08x",
+          properties.implementor.c_str(), properties.recognitionModes);
+
+exit:
+    _hidl_cb(ret, properties);
+    return Void();
+}
+
+int SoundTriggerHalImpl::doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                                                 const sp<ISoundTriggerHwCallback>& callback,
+                                                 ISoundTriggerHwCallback::CallbackCookie cookie,
+                                                 uint32_t *modelId)
+{
+    int32_t ret = 0;
+    struct sound_trigger_sound_model *halSoundModel;
+    *modelId = 0;
+    sp<SoundModelClient> client;
+
+    ALOGV("doLoadSoundModel() data size %zu", soundModel.data.size());
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    halSoundModel = convertSoundModelToHal(&soundModel);
+    if (halSoundModel == NULL) {
+        ret = -EINVAL;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        do {
+            *modelId = nextUniqueId();
+        } while (mClients.valueFor(*modelId) != 0 && *modelId != 0);
+    }
+    LOG_ALWAYS_FATAL_IF(*modelId == 0,
+                        "wrap around in sound model IDs, num loaded models %d", mClients.size());
+
+    client = new SoundModelClient(*modelId, callback, cookie);
+
+    ret = mHwDevice->load_sound_model(mHwDevice, halSoundModel, soundModelCallback,
+                                          client.get(), &client->mHalHandle);
+
+    free(halSoundModel);
+
+    if (ret != 0) {
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        mClients.add(*modelId, client);
+    }
+
+exit:
+    return ret;
+}
+
+Return<void> SoundTriggerHalImpl::loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                                                 const sp<ISoundTriggerHwCallback>& callback,
+                                                 ISoundTriggerHwCallback::CallbackCookie cookie,
+                                                 loadSoundModel_cb _hidl_cb)
+{
+    uint32_t modelId = 0;
+    int32_t ret = doLoadSoundModel(soundModel, callback, cookie, &modelId);
+
+    _hidl_cb(ret, modelId);
+    return Void();
+}
+
+Return<void> SoundTriggerHalImpl::loadPhraseSoundModel(
+                                            const ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                            const sp<ISoundTriggerHwCallback>& callback,
+                                            ISoundTriggerHwCallback::CallbackCookie cookie,
+                                            ISoundTriggerHw::loadPhraseSoundModel_cb _hidl_cb)
+{
+    uint32_t modelId = 0;
+    int32_t ret = doLoadSoundModel((const ISoundTriggerHw::SoundModel&)soundModel,
+                                   callback, cookie, &modelId);
+
+    _hidl_cb(ret, modelId);
+    return Void();
+}
+
+Return<int32_t> SoundTriggerHalImpl::unloadSoundModel(SoundModelHandle modelHandle)
+{
+    int32_t ret;
+    sp<SoundModelClient> client;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    ret = mHwDevice->unload_sound_model(mHwDevice, client->mHalHandle);
+
+    mClients.removeItem(modelHandle);
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHalImpl::startRecognition(SoundModelHandle modelHandle,
+                                           const ISoundTriggerHw::RecognitionConfig& config,
+                                           const sp<ISoundTriggerHwCallback>& callback __unused,
+                                           ISoundTriggerHwCallback::CallbackCookie cookie __unused)
+{
+    int32_t ret;
+    sp<SoundModelClient> client;
+    struct sound_trigger_recognition_config *halConfig;
+
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+
+    halConfig = convertRecognitionConfigToHal(&config);
+
+    if (halConfig == NULL) {
+        ret = -EINVAL;
+        goto exit;
+    }
+    ret = mHwDevice->start_recognition(mHwDevice, client->mHalHandle, halConfig,
+                                 recognitionCallback, client.get());
+
+    free(halConfig);
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHalImpl::stopRecognition(SoundModelHandle modelHandle)
+{
+    int32_t ret;
+    sp<SoundModelClient> client;
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    {
+        AutoMutex lock(mLock);
+        client = mClients.valueFor(modelHandle);
+        if (client == 0) {
+            ret = -ENOSYS;
+            goto exit;
+        }
+    }
+
+    ret = mHwDevice->stop_recognition(mHwDevice, client->mHalHandle);
+
+exit:
+    return ret;
+}
+
+Return<int32_t> SoundTriggerHalImpl::stopAllRecognitions()
+{
+    int32_t ret;
+    if (mHwDevice == NULL) {
+        ret = -ENODEV;
+        goto exit;
+    }
+
+    if (mHwDevice->common.version >= SOUND_TRIGGER_DEVICE_API_VERSION_1_1 &&
+            mHwDevice->stop_all_recognitions) {
+        ret = mHwDevice->stop_all_recognitions(mHwDevice);
+    } else {
+        ret = -ENOSYS;
+    }
+exit:
+    return ret;
+}
+
+SoundTriggerHalImpl::SoundTriggerHalImpl(const char *moduleName)
+    : mModuleName(moduleName), mHwDevice(NULL), mNextModelId(1)
+{
+}
+
+void SoundTriggerHalImpl::onFirstRef()
+{
+    const hw_module_t *mod;
+    int rc;
+
+    if (mModuleName == NULL || strlen(mModuleName) == 0) {
+        mModuleName = "primary";
+    }
+    rc = hw_get_module_by_class(SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, &mod);
+    if (rc != 0) {
+        ALOGE("couldn't load sound trigger module %s.%s (%s)",
+              SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+        return;
+    }
+    rc = sound_trigger_hw_device_open(mod, &mHwDevice);
+    if (rc != 0) {
+        ALOGE("couldn't open sound trigger hw device in %s.%s (%s)",
+              SOUND_TRIGGER_HARDWARE_MODULE_ID, mModuleName, strerror(-rc));
+        mHwDevice = NULL;
+        return;
+    }
+    if (mHwDevice->common.version < SOUND_TRIGGER_DEVICE_API_VERSION_1_0 ||
+            mHwDevice->common.version > SOUND_TRIGGER_DEVICE_API_VERSION_CURRENT) {
+        ALOGE("wrong sound trigger hw device version %04x", mHwDevice->common.version);
+        sound_trigger_hw_device_close(mHwDevice);
+        mHwDevice = NULL;
+        return;
+    }
+
+    ALOGI("onFirstRef() mModuleName %s mHwDevice %p", mModuleName, mHwDevice);
+}
+
+SoundTriggerHalImpl::~SoundTriggerHalImpl()
+{
+    if (mHwDevice != NULL) {
+        sound_trigger_hw_device_close(mHwDevice);
+    }
+}
+
+uint32_t SoundTriggerHalImpl::nextUniqueId()
+{
+    return (uint32_t) atomic_fetch_add_explicit(&mNextModelId,
+                (uint_fast32_t) 1, memory_order_acq_rel);
+}
+
+void SoundTriggerHalImpl::convertUuidFromHal(Uuid *uuid,
+                                             const sound_trigger_uuid_t *halUuid)
+{
+    uuid->timeLow = halUuid->timeLow;
+    uuid->timeMid = halUuid->timeMid;
+    uuid->versionAndTimeHigh = halUuid->timeHiAndVersion;
+    uuid->variantAndClockSeqHigh = halUuid->clockSeq;
+    memcpy(&uuid->node[0], &halUuid->node[0], 6);
+}
+
+void SoundTriggerHalImpl::convertUuidToHal(sound_trigger_uuid_t *halUuid,
+                                           const Uuid *uuid)
+{
+    halUuid->timeLow = uuid->timeLow;
+    halUuid->timeMid = uuid->timeMid;
+    halUuid->timeHiAndVersion = uuid->versionAndTimeHigh;
+    halUuid->clockSeq = uuid->variantAndClockSeqHigh;
+    memcpy(&halUuid->node[0], &uuid->node[0], 6);
+}
+
+void SoundTriggerHalImpl::convertPropertiesFromHal(
+        ISoundTriggerHw::Properties *properties,
+        const struct sound_trigger_properties *halProperties)
+{
+    properties->implementor = halProperties->implementor;
+    properties->description = halProperties->description;
+    properties->version = halProperties->version;
+    convertUuidFromHal(&properties->uuid, &halProperties->uuid);
+    properties->maxSoundModels = halProperties->max_sound_models;
+    properties->maxKeyPhrases = halProperties->max_key_phrases;
+    properties->maxUsers = halProperties->max_users;
+    properties->recognitionModes = halProperties->recognition_modes;
+    properties->captureTransition = halProperties->capture_transition;
+    properties->maxBufferMs = halProperties->max_buffer_ms;
+    properties->concurrentCapture = halProperties->concurrent_capture;
+    properties->triggerInEvent = halProperties->trigger_in_event;
+    properties->powerConsumptionMw = halProperties->power_consumption_mw;
+
+}
+
+void SoundTriggerHalImpl::convertTriggerPhraseToHal(
+        struct sound_trigger_phrase *halTriggerPhrase,
+        const ISoundTriggerHw::Phrase *triggerPhrase)
+{
+    halTriggerPhrase->id = triggerPhrase->id;
+    halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
+    unsigned int i;
+    for (i = 0; i < triggerPhrase->users.size(); i++) {
+        halTriggerPhrase->users[i] = triggerPhrase->users[i];
+    }
+    halTriggerPhrase->num_users = i;
+
+    strlcpy(halTriggerPhrase->locale,
+            triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
+    strlcpy(halTriggerPhrase->text,
+            triggerPhrase->text.c_str(), SOUND_TRIGGER_MAX_STRING_LEN);
+}
+
+struct sound_trigger_sound_model *SoundTriggerHalImpl::convertSoundModelToHal(
+        const ISoundTriggerHw::SoundModel *soundModel)
+{
+    struct sound_trigger_sound_model *halModel = NULL;
+    if (soundModel->type == SoundModelType::KEYPHRASE) {
+        size_t allocSize =
+                sizeof(struct sound_trigger_phrase_sound_model) + soundModel->data.size();
+        struct sound_trigger_phrase_sound_model *halKeyPhraseModel =
+                static_cast<struct sound_trigger_phrase_sound_model *>(malloc(allocSize));
+        LOG_ALWAYS_FATAL_IF(halKeyPhraseModel == NULL,
+                        "malloc failed for size %zu in convertSoundModelToHal PHRASE", allocSize);
+
+        const ISoundTriggerHw::PhraseSoundModel *keyPhraseModel =
+                reinterpret_cast<const ISoundTriggerHw::PhraseSoundModel *>(soundModel);
+
+        size_t i;
+        for (i = 0; i < keyPhraseModel->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+            convertTriggerPhraseToHal(&halKeyPhraseModel->phrases[i],
+                                      &keyPhraseModel->phrases[i]);
+        }
+        halKeyPhraseModel->num_phrases = (unsigned int)i;
+        halModel = reinterpret_cast<struct sound_trigger_sound_model *>(halKeyPhraseModel);
+        halModel->data_offset = sizeof(struct sound_trigger_phrase_sound_model);
+    } else {
+        size_t allocSize =
+                sizeof(struct sound_trigger_sound_model) + soundModel->data.size();
+        halModel = static_cast<struct sound_trigger_sound_model *>(malloc(allocSize));
+        LOG_ALWAYS_FATAL_IF(halModel == NULL,
+                            "malloc failed for size %zu in convertSoundModelToHal GENERIC",
+                            allocSize);
+
+        halModel->data_offset = sizeof(struct sound_trigger_sound_model);
+    }
+    halModel->type = (sound_trigger_sound_model_type_t)soundModel->type;
+    convertUuidToHal(&halModel->uuid, &soundModel->uuid);
+    convertUuidToHal(&halModel->vendor_uuid, &soundModel->vendorUuid);
+    halModel->data_size = soundModel->data.size();
+    uint8_t *dst = reinterpret_cast<uint8_t *>(halModel) + halModel->data_offset;
+    const uint8_t *src = reinterpret_cast<const uint8_t *>(&soundModel->data[0]);
+    memcpy(dst, src, soundModel->data.size());
+
+    return halModel;
+}
+
+void SoundTriggerHalImpl::convertPhraseRecognitionExtraToHal(
+        struct sound_trigger_phrase_recognition_extra *halExtra,
+        const PhraseRecognitionExtra *extra)
+{
+    halExtra->id = extra->id;
+    halExtra->recognition_modes = extra->recognitionModes;
+    halExtra->confidence_level = extra->confidenceLevel;
+
+    unsigned int i;
+    for (i = 0; i < extra->levels.size() && i < SOUND_TRIGGER_MAX_USERS; i++) {
+        halExtra->levels[i].user_id = extra->levels[i].userId;
+        halExtra->levels[i].level = extra->levels[i].levelPercent;
+    }
+    halExtra->num_levels = i;
+}
+
+struct sound_trigger_recognition_config *SoundTriggerHalImpl::convertRecognitionConfigToHal(
+        const ISoundTriggerHw::RecognitionConfig *config)
+{
+    size_t allocSize = sizeof(struct sound_trigger_recognition_config) + config->data.size();
+    struct sound_trigger_recognition_config *halConfig =
+            static_cast<struct sound_trigger_recognition_config *>(malloc(allocSize));
+
+    LOG_ALWAYS_FATAL_IF(halConfig == NULL,
+                        "malloc failed for size %zu in convertRecognitionConfigToHal",
+                        allocSize);
+
+    halConfig->capture_handle = (audio_io_handle_t)config->captureHandle;
+    halConfig->capture_device = (audio_devices_t)config->captureDevice;
+    halConfig->capture_requested = config->captureRequested;
+
+    unsigned int i;
+    for (i = 0; i < config->phrases.size() && i < SOUND_TRIGGER_MAX_PHRASES; i++) {
+        convertPhraseRecognitionExtraToHal(&halConfig->phrases[i],
+                                  &config->phrases[i]);
+    }
+    halConfig->num_phrases = i;
+
+    halConfig->data_offset = sizeof(struct sound_trigger_recognition_config);
+    halConfig->data_size = config->data.size();
+    uint8_t *dst = reinterpret_cast<uint8_t *>(halConfig) + halConfig->data_offset;
+    const uint8_t *src = reinterpret_cast<const uint8_t *>(&config->data[0]);
+    memcpy(dst, src, config->data.size());
+    return halConfig;
+}
+
+// static
+void SoundTriggerHalImpl::convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
+                                                const struct sound_trigger_model_event *halEvent)
+{
+    event->status = (ISoundTriggerHwCallback::SoundModelStatus)halEvent->status;
+    // event->model to be remapped by called
+    event->data.setToExternal(
+            const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
+            halEvent->data_size);
+}
+
+// static
+ISoundTriggerHwCallback::RecognitionEvent *SoundTriggerHalImpl::convertRecognitionEventFromHal(
+                                            const struct sound_trigger_recognition_event *halEvent)
+{
+    ISoundTriggerHwCallback::RecognitionEvent * event;
+
+    if (halEvent->type == SOUND_MODEL_TYPE_KEYPHRASE) {
+        const struct sound_trigger_phrase_recognition_event *halPhraseEvent =
+                reinterpret_cast<const struct sound_trigger_phrase_recognition_event *>(halEvent);
+        ISoundTriggerHwCallback::PhraseRecognitionEvent *phraseEvent =
+                new ISoundTriggerHwCallback::PhraseRecognitionEvent();
+
+        PhraseRecognitionExtra *phraseExtras =
+                new PhraseRecognitionExtra[halPhraseEvent->num_phrases];
+        for (unsigned int i = 0; i < halPhraseEvent->num_phrases; i++) {
+            convertPhraseRecognitionExtraFromHal(&phraseExtras[i],
+                                                 &halPhraseEvent->phrase_extras[i]);
+        }
+        phraseEvent->phraseExtras.setToExternal(phraseExtras, halPhraseEvent->num_phrases);
+        // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+        phraseEvent->phraseExtras.resize(halPhraseEvent->num_phrases);
+        delete[] phraseExtras;
+        event = reinterpret_cast<ISoundTriggerHwCallback::RecognitionEvent *>(phraseEvent);
+    } else {
+        event = new ISoundTriggerHwCallback::RecognitionEvent();
+    }
+
+    event->status = static_cast<ISoundTriggerHwCallback::RecognitionStatus>(halEvent->status);
+    event->type = static_cast<SoundModelType>(halEvent->type);
+    // event->model to be remapped by called
+    event->captureAvailable = halEvent->capture_available;
+    event->captureSession = halEvent->capture_session;
+    event->captureDelayMs = halEvent->capture_delay_ms;
+    event->capturePreambleMs = halEvent->capture_preamble_ms;
+    event->triggerInData = halEvent->trigger_in_data;
+    event->audioConfig.sampleRateHz = halEvent->audio_config.sample_rate;
+    event->audioConfig.channelMask =
+            (audio::common::V2_0::AudioChannelMask)halEvent->audio_config.channel_mask;
+    event->audioConfig.format = (audio::common::V2_0::AudioFormat)halEvent->audio_config.format;
+    event->data.setToExternal(
+            const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(halEvent)) + halEvent->data_offset,
+            halEvent->data_size);
+
+    return event;
+}
+
+// static
+void SoundTriggerHalImpl::convertPhraseRecognitionExtraFromHal(
+        PhraseRecognitionExtra *extra,
+        const struct sound_trigger_phrase_recognition_extra *halExtra)
+{
+    extra->id = halExtra->id;
+    extra->recognitionModes = halExtra->recognition_modes;
+    extra->confidenceLevel = halExtra->confidence_level;
+
+    ConfidenceLevel *levels =
+            new ConfidenceLevel[halExtra->num_levels];
+    for (unsigned int i = 0; i < halExtra->num_levels; i++) {
+        levels[i].userId = halExtra->levels[i].user_id;
+        levels[i].levelPercent = halExtra->levels[i].level;
+    }
+    extra->levels.setToExternal(levels, halExtra->num_levels);
+    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
+    extra->levels.resize(halExtra->num_levels);
+    delete[] levels;
+}
+
+ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char *name)
+{
+    if (name != NULL) {
+        if (strncmp(SOUND_TRIGGER_HARDWARE_MODULE_ID, name,
+                strlen(SOUND_TRIGGER_HARDWARE_MODULE_ID)) != 0) {
+            return NULL;
+        }
+        name = strchr(name, '.');
+        if (name == NULL) {
+            return NULL;
+        }
+        name++;
+    }
+    return new SoundTriggerHalImpl(name);
+}
+} // namespace implementation
+}  // namespace V2_0
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
+
+
+
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.h b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
new file mode 100644
index 0000000..4e0d01d
--- /dev/null
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.h
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_SOUNDTRIGGER_V2_0_IMPLEMENTATION_H
+#define ANDROID_HARDWARE_SOUNDTRIGGER_V2_0_IMPLEMENTATION_H
+
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHwCallback.h>
+#include <hidl/Status.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+#include <system/sound_trigger.h>
+#include <hardware/sound_trigger.h>
+
+namespace android {
+namespace hardware {
+namespace soundtrigger {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::Uuid;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+
+
+class SoundTriggerHalImpl : public ISoundTriggerHw {
+public:
+        explicit SoundTriggerHalImpl(const char *moduleName = NULL);
+
+        // Methods from ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw follow.
+        Return<void> getProperties(getProperties_cb _hidl_cb)  override;
+        Return<void> loadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                                    const sp<ISoundTriggerHwCallback>& callback,
+                                    ISoundTriggerHwCallback::CallbackCookie cookie,
+                                    loadSoundModel_cb _hidl_cb)  override;
+        Return<void> loadPhraseSoundModel(const ISoundTriggerHw::PhraseSoundModel& soundModel,
+                                    const sp<ISoundTriggerHwCallback>& callback,
+                                    ISoundTriggerHwCallback::CallbackCookie cookie,
+                                    loadPhraseSoundModel_cb _hidl_cb)  override;
+
+        Return<int32_t> unloadSoundModel(SoundModelHandle modelHandle)  override;
+        Return<int32_t> startRecognition(SoundModelHandle modelHandle,
+                                      const ISoundTriggerHw::RecognitionConfig& config,
+                                      const sp<ISoundTriggerHwCallback>& callback,
+                                      ISoundTriggerHwCallback::CallbackCookie cookie)  override;
+        Return<int32_t> stopRecognition(SoundModelHandle modelHandle)  override;
+        Return<int32_t> stopAllRecognitions()  override;
+
+        // RefBase
+        virtual     void        onFirstRef();
+
+        static void soundModelCallback(struct sound_trigger_model_event *halEvent,
+                                       void *cookie);
+        static void recognitionCallback(struct sound_trigger_recognition_event *halEvent,
+                                        void *cookie);
+
+private:
+
+        class SoundModelClient : public RefBase {
+        public:
+            SoundModelClient(uint32_t id, sp<ISoundTriggerHwCallback> callback,
+                             ISoundTriggerHwCallback::CallbackCookie cookie)
+                : mId(id), mCallback(callback), mCookie(cookie) {}
+            virtual ~SoundModelClient() {}
+
+            uint32_t mId;
+            sound_model_handle_t mHalHandle;
+            sp<ISoundTriggerHwCallback> mCallback;
+            ISoundTriggerHwCallback::CallbackCookie mCookie;
+        };
+
+        uint32_t nextUniqueId();
+        void convertUuidFromHal(Uuid *uuid,
+                                const sound_trigger_uuid_t *halUuid);
+        void convertUuidToHal(sound_trigger_uuid_t *halUuid,
+                              const Uuid *uuid);
+        void convertPropertiesFromHal(ISoundTriggerHw::Properties *properties,
+                                      const struct sound_trigger_properties *halProperties);
+        void convertTriggerPhraseToHal(struct sound_trigger_phrase *halTriggerPhrase,
+                                       const ISoundTriggerHw::Phrase *triggerPhrase);
+        // returned HAL sound model must be freed by caller
+        struct sound_trigger_sound_model *convertSoundModelToHal(
+                    const ISoundTriggerHw::SoundModel *soundModel);
+        void convertPhraseRecognitionExtraToHal(
+                struct sound_trigger_phrase_recognition_extra *halExtra,
+                const PhraseRecognitionExtra *extra);
+        // returned recognition config must be freed by caller
+        struct sound_trigger_recognition_config *convertRecognitionConfigToHal(
+                const ISoundTriggerHw::RecognitionConfig *config);
+
+
+        static void convertSoundModelEventFromHal(ISoundTriggerHwCallback::ModelEvent *event,
+                                            const struct sound_trigger_model_event *halEvent);
+        static ISoundTriggerHwCallback::RecognitionEvent *convertRecognitionEventFromHal(
+                                            const struct sound_trigger_recognition_event *halEvent);
+        static void convertPhraseRecognitionExtraFromHal(PhraseRecognitionExtra *extra,
+                                    const struct sound_trigger_phrase_recognition_extra *halExtra);
+
+        int doLoadSoundModel(const ISoundTriggerHw::SoundModel& soundModel,
+                             const sp<ISoundTriggerHwCallback>& callback,
+                             ISoundTriggerHwCallback::CallbackCookie cookie,
+                             uint32_t *modelId);
+
+        virtual             ~SoundTriggerHalImpl();
+
+        const char *                                        mModuleName;
+        struct sound_trigger_hw_device*                     mHwDevice;
+        volatile atomic_uint_fast32_t                       mNextModelId;
+        DefaultKeyedVector<int32_t, sp<SoundModelClient> >  mClients;
+        Mutex                                               mLock;
+};
+
+extern "C" ISoundTriggerHw *HIDL_FETCH_ISoundTriggerHw(const char *name);
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace soundtrigger
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_SOUNDTRIGGER_V2_0_IMPLEMENTATION_H
+
diff --git a/soundtrigger/2.0/types.hal b/soundtrigger/2.0/types.hal
new file mode 100644
index 0000000..26928ba
--- /dev/null
+++ b/soundtrigger/2.0/types.hal
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+package android.hardware.soundtrigger@2.0;
+
+/*
+ * Sound model types modes used in ISoundTriggerHw.SoundModel
+ */
+enum SoundModelType : int32_t {
+    /* use for unspecified sound model type */
+    UNKNOWN   = -1,
+    /* use for key phrase sound models */
+    KEYPHRASE = 0,
+    /* use for all models other than keyphrase */
+    GENERIC   = 1,
+};
+
+typedef int32_t SoundModelHandle;
+
+
+/*
+ * Recognition modes used in ISoundTriggerHw.RecognitionConfig,
+ * ISoundTriggerHw.Properties or PhraseRecognitionExtra
+ */
+enum RecognitionMode : uint32_t {
+    /* simple voice trigger */
+    VOICE_TRIGGER       = (1 << 0),
+    /* trigger only if one user in model identified */
+    USER_IDENTIFICATION = (1 << 1),
+    /* trigger only if one user in mode authenticated */
+    USER_AUTHENTICATION = (1 << 2),
+    /* generic sound trigger */
+    GENERIC_TRIGGER     = (1 << 3),
+};
+
+/*
+ * Confidence level for each user in structure PhraseRecognitionExtra
+ */
+struct ConfidenceLevel {
+    /* user ID */
+    uint32_t userId;
+    /* confidence level in percent (0 - 100): */
+    /* - min level for recognition configuration */
+    /* - detected level for recognition event */
+    uint32_t levelPercent;
+};
+
+/*
+ * Specialized recognition event for key phrase detection
+ */
+struct PhraseRecognitionExtra {
+    /* keyphrase ID */
+    uint32_t id;
+    /* recognition modes used for this keyphrase */
+    uint32_t recognitionModes;
+    /* confidence level for mode RecognitionMode.VOICE_TRIGGER */
+    uint32_t confidenceLevel;
+    /* list of confidence levels per user for
+     * RecognitionMode.USER_IDENTIFICATION and
+     * RecognitionMode.USER_AUTHENTICATION */
+    vec<ConfidenceLevel> levels;
+};
+
+/* TODO(elaurent) remove when Java build problem is fixed */
+union Dummy {
+  uint32_t dummy1;
+  int32_t dummy2;
+};
\ No newline at end of file
diff --git a/soundtrigger/2.0/vts/Android.mk b/soundtrigger/2.0/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/Android.bp b/soundtrigger/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..8abdf06
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/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_test {
+    name: "soundtrigger_hidl_hal_test",
+    gtest: true,
+    srcs: ["soundtrigger_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.soundtrigger@2.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/soundtrigger/2.0/vts/functional/Android.mk b/soundtrigger/2.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/soundtrigger_hidl_hal_test.cpp b/soundtrigger/2.0/vts/functional/soundtrigger_hidl_hal_test.cpp
new file mode 100644
index 0000000..cb00ad5
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/soundtrigger_hidl_hal_test.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SoundTriggerHidlHalTest"
+#include <android/log.h>
+#include <cutils/native_handle.h>
+
+#include <android/hardware/audio/common/2.0/types.h>
+#include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
+#include <android/hardware/soundtrigger/2.0/types.h>
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::soundtrigger::V2_0::SoundModelHandle;
+using ::android::hardware::soundtrigger::V2_0::SoundModelType;
+using ::android::hardware::soundtrigger::V2_0::RecognitionMode;
+using ::android::hardware::soundtrigger::V2_0::PhraseRecognitionExtra;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
+using ::android::hardware::soundtrigger::V2_0::ISoundTriggerHwCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Status;
+using ::android::hardware::Void;
+using ::android::sp;
+
+// The main test class for Sound Trigger HIDL HAL.
+class SoundTriggerHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    mSoundTriggerHal = ISoundTriggerHw::getService("sound_trigger.primary");
+    ASSERT_NE(nullptr, mSoundTriggerHal.get());
+    mCallback = new MyCallback();
+    ASSERT_NE(nullptr, mCallback.get());
+  }
+
+  class MyCallback : public ISoundTriggerHwCallback {
+      virtual Return<void> recognitionCallback(
+                  const ISoundTriggerHwCallback::RecognitionEvent& event __unused,
+                  int32_t cookie __unused) {
+          ALOGI("%s", __FUNCTION__);
+          return Void();
+      }
+
+      virtual Return<void> phraseRecognitionCallback(
+              const ISoundTriggerHwCallback::PhraseRecognitionEvent& event __unused,
+              int32_t cookie __unused) {
+          ALOGI("%s", __FUNCTION__);
+          return Void();
+      }
+
+      virtual Return<void> soundModelCallback(
+              const ISoundTriggerHwCallback::ModelEvent& event __unused,
+              int32_t cookie __unused) {
+          ALOGI("%s", __FUNCTION__);
+          return Void();
+      }
+  };
+
+  virtual void TearDown() override {}
+
+  sp<ISoundTriggerHw> mSoundTriggerHal;
+  sp<MyCallback> mCallback;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class SoundTriggerHidlEnvironment : public ::testing::Environment {
+ public:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ private:
+};
+
+/**
+ * Test ISoundTriggerHw::getProperties() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the method returns 0 (no error)
+ *  - the implementation supports at least one sound model and one key phrase
+ *  - the implementation supports at least VOICE_TRIGGER recognition mode
+ */
+TEST_F(SoundTriggerHidlTest, GetProperties) {
+  ISoundTriggerHw::Properties halProperties;
+  Return<void> hidlReturn;
+  int ret = -ENODEV;
+
+  hidlReturn = mSoundTriggerHal->getProperties([&](int rc, auto res) {
+      ret = rc;
+      halProperties = res;
+  });
+
+  EXPECT_TRUE(hidlReturn.isOk());
+  EXPECT_EQ(0, ret);
+  EXPECT_GT(halProperties.maxSoundModels, 0u);
+  EXPECT_GT(halProperties.maxKeyPhrases, 0u);
+  EXPECT_NE(0u, (halProperties.recognitionModes & (uint32_t)RecognitionMode::VOICE_TRIGGER));
+}
+
+/**
+ * Test ISoundTriggerHw::loadPhraseSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when passed a malformed sound model
+ *
+ * There is no way to verify that implementation actually can load a sound model because each
+ * sound model is vendor specific.
+ */
+TEST_F(SoundTriggerHidlTest, LoadInvalidModelFail) {
+  Return<void> hidlReturn;
+  int ret = -ENODEV;
+  ISoundTriggerHw::PhraseSoundModel model;
+  SoundModelHandle handle;
+
+  model.common.type = SoundModelType::UNKNOWN;
+
+  hidlReturn = mSoundTriggerHal->loadPhraseSoundModel(
+          model,
+          mCallback, 0, [&](int32_t retval, auto res) {
+      ret = retval;
+      handle = res;
+  });
+
+  EXPECT_TRUE(hidlReturn.isOk());
+  EXPECT_NE(0, ret);
+}
+
+/**
+ * Test ISoundTriggerHw::unloadSoundModel() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without a valid loaded sound model
+ *
+ */
+TEST_F(SoundTriggerHidlTest, UnloadModelNoModelFail) {
+  Return<int32_t> hidlReturn(0);
+  SoundModelHandle halHandle = 0;
+
+  hidlReturn = mSoundTriggerHal->unloadSoundModel(halHandle);
+
+  EXPECT_TRUE(hidlReturn.isOk());
+  EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::startRecognition() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without a valid loaded sound model
+ *
+ * There is no way to verify that implementation actually starts recognition because no model can
+ * be loaded.
+ */
+TEST_F(SoundTriggerHidlTest, StartRecognitionNoModelFail) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+    PhraseRecognitionExtra phrase;
+    ISoundTriggerHw::RecognitionConfig config;
+
+    config.captureHandle = 0;
+    config.captureDevice = AudioDevice::IN_BUILTIN_MIC;
+    phrase.id = 0;
+    phrase.recognitionModes = (uint32_t)RecognitionMode::VOICE_TRIGGER;
+    phrase.confidenceLevel = 0;
+
+    config.phrases.setToExternal(&phrase, 1);
+
+    hidlReturn = mSoundTriggerHal->startRecognition(handle, config, mCallback, 0);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopRecognition() method
+ *
+ * Verifies that:
+ *  - the implementation implements the method
+ *  - the implementation returns an error when called without an active recognition running
+ *
+ */
+TEST_F(SoundTriggerHidlTest, StopRecognitionNoAStartFail) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+
+    hidlReturn = mSoundTriggerHal->stopRecognition(handle);
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_NE(0, hidlReturn);
+}
+
+/**
+ * Test ISoundTriggerHw::stopAllRecognitions() method
+ *
+ * Verifies that:
+ *  - the implementation implements this optional method or indicates it is not support by
+ *  returning -ENOSYS
+ */
+TEST_F(SoundTriggerHidlTest, stopAllRecognitions) {
+    Return<int32_t> hidlReturn(0);
+    SoundModelHandle handle = 0;
+
+    hidlReturn = mSoundTriggerHal->stopAllRecognitions();
+
+    EXPECT_TRUE(hidlReturn.isOk());
+    EXPECT_TRUE(hidlReturn == 0 || hidlReturn == -ENOSYS);
+}
+
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(new SoundTriggerHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/soundtrigger/2.0/vts/functional/vts/Android.mk b/soundtrigger/2.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/Android.mk
new file mode 100644
index 0000000..a99f4ce
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalSoundTriggerHidlTargetBasicTest
+VTS_CONFIG_SRC_DIR := testcases/hal/soundtrigger/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..9339165
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS sound trigger HIDL HAL's basic target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalSoundTriggerHidlTargetBasicTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
+            _64bit::DATA/nativetest64/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
+            "/>
+        <option name="test-config-path" value="vts/testcases/hal/soundtrigger/hidl/target/HalSoundTriggerHidlTargetBasicTest.config" />
+        <option name="binary-test-type" value="hal_hidl_gtest" />
+        <option name="precondition-file-path-prefix" value="*/lib/hw/sound_trigger.primary." />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/HalSoundTriggerHidlTargetBasicTest.config b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/HalSoundTriggerHidlTargetBasicTest.config
new file mode 100644
index 0000000..5c12d13
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target/HalSoundTriggerHidlTargetBasicTest.config
@@ -0,0 +1,41 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [
+        {
+            "module_name": "system/lib/hw/sound_trigger.primary.bullhead",
+            "git_project": {
+                "name": "platform/vendor/lge/bullhead",
+                "path": "vendor/lge/bullhead"
+            }
+        },
+        {
+            "module_name": "system/lib/hw/sound_trigger.primary.angler",
+            "git_project": {
+                "name": "platform/vendor/huawei/angler",
+                "path": "vendor/huawei/angler"
+            }
+        },
+        {
+            "module_name": "system/lib/hw/sound_trigger.primary.marlin",
+            "git_project": {
+                "name": "platform/vendor/google_devices/marlin",
+                "path": "vendor/google_devices/marlin"
+            }
+        },
+        {
+            "module_name": "system/lib/hw/sound_trigger.primary.sailfish",
+            "git_project": {
+                "name": "platform/vendor/google_devices/marlin",
+                "path": "vendor/google_devices/marlin"
+            }
+        },
+        {
+            "module_name": "system/lib/hw/android.hardware.soundtrigger@2.0-impl",
+            "git_project": {
+                "name": "platform/hardware/interfaces",
+                "path": "hardware/interfaces"
+            }
+        }
+    ]
+}
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/Android.mk b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..fc0f9c4
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := HalSoundTriggerHidlTargetBasicProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/soundtrigger/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..e95a406
--- /dev/null
+++ b/soundtrigger/2.0/vts/functional/vts/testcases/hal/soundtrigger/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS sound trigger HIDL HAL's basic target-side, profiling test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="HalSoundTriggerHidlTargetBasicTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
+            _64bit::DATA/nativetest64/soundtrigger_hidl_hal_test/soundtrigger_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/soundtrigger/Android.bp b/soundtrigger/Android.bp
new file mode 100644
index 0000000..8d2c986
--- /dev/null
+++ b/soundtrigger/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "2.0",
+    "2.0/vts/functional",
+]
diff --git a/tests/bar/Android.mk b/tests/bar/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/bar/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/baz/Android.mk b/tests/baz/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/baz/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/expression/Android.mk b/tests/expression/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/expression/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/foo/Android.mk b/tests/foo/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/foo/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/inheritance/Android.mk b/tests/inheritance/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/inheritance/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/libhwbinder/Android.mk b/tests/libhwbinder/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/libhwbinder/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/msgq/Android.mk b/tests/msgq/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/msgq/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tests/pointer/Android.mk b/tests/pointer/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tests/pointer/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/Android.bp b/thermal/1.0/Android.bp
new file mode 100644
index 0000000..e80bedc
--- /dev/null
+++ b/thermal/1.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.thermal@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0",
+    srcs: [
+        "types.hal",
+        "IThermal.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/types.cpp",
+        "android/hardware/thermal/1.0/ThermalAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0",
+    srcs: [
+        "types.hal",
+        "IThermal.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/types.h",
+        "android/hardware/thermal/1.0/IThermal.h",
+        "android/hardware/thermal/1.0/IHwThermal.h",
+        "android/hardware/thermal/1.0/BnHwThermal.h",
+        "android/hardware/thermal/1.0/BpHwThermal.h",
+        "android/hardware/thermal/1.0/BsThermal.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.thermal@1.0",
+    generated_sources: ["android.hardware.thermal@1.0_genc++"],
+    generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/thermal/1.0/ $(genDir)/android/hardware/thermal/1.0/",
+    srcs: [
+        "types.hal",
+        "IThermal.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/types.vts.cpp",
+        "android/hardware/thermal/1.0/Thermal.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/thermal/1.0/ $(genDir)/android/hardware/thermal/1.0/",
+    srcs: [
+        "types.hal",
+        "IThermal.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/types.vts.h",
+        "android/hardware/thermal/1.0/Thermal.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.thermal.vts.driver@1.0",
+    generated_sources: ["android.hardware.thermal.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.thermal.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.thermal.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.thermal@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.0-IThermal-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/thermal/1.0/ $(genDir)/android/hardware/thermal/1.0/",
+    srcs: [
+        "IThermal.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/Thermal.vts.cpp",
+        "android/hardware/thermal/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.0-IThermal-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/thermal/1.0/ $(genDir)/android/hardware/thermal/1.0/",
+    srcs: [
+        "IThermal.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.0/Thermal.vts.h",
+        "android/hardware/thermal/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.thermal@1.0-IThermal-vts.profiler",
+    generated_sources: ["android.hardware.thermal@1.0-IThermal-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.thermal@1.0-IThermal-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.thermal@1.0-IThermal-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.thermal@1.0",
+    ],
+}
diff --git a/thermal/1.0/Android.mk b/thermal/1.0/Android.mk
new file mode 100644
index 0000000..b88bb81
--- /dev/null
+++ b/thermal/1.0/Android.mk
@@ -0,0 +1,380 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (CoolingDevice)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CoolingDevice.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CoolingDevice
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CoolingType)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CoolingType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CoolingType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CpuUsage)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CpuUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CpuUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Temperature)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/Temperature.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.Temperature
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TemperatureType)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/TemperatureType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.TemperatureType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ThermalStatus)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/ThermalStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.ThermalStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ThermalStatusCode)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/ThermalStatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.ThermalStatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (CoolingDevice)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CoolingDevice.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CoolingDevice
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CoolingType)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CoolingType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CoolingType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CpuUsage)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/CpuUsage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.CpuUsage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Temperature)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/Temperature.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.Temperature
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (TemperatureType)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/TemperatureType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.TemperatureType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ThermalStatus)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/ThermalStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.ThermalStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (ThermalStatusCode)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/ThermalStatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::types.ThermalStatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/thermal/1.0/IThermal.hal b/thermal/1.0/IThermal.hal
new file mode 100644
index 0000000..e5f70cb
--- /dev/null
+++ b/thermal/1.0/IThermal.hal
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.0;
+
+interface IThermal {
+
+    /*
+     * Retrieves temperatures in Celsius.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *         the status.debugMessage must be populated with the human-readable
+     *         error message.
+     * @return temperatures If status code is SUCCESS, it's filled with the
+     *         current temperatures. The order of temperatures of built-in
+     *         devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *         the same regardless the number of calls to this method even if
+     *         they go offline, if these devices exist on boot. The method
+     *         always returns and never removes such temperatures.
+     *
+     */
+    @callflow(next={"*"})
+    @entry
+    @exit
+    getTemperatures()
+        generates (ThermalStatus status, vec<Temperature> temperatures);
+
+    /*
+     * Retrieves CPU usage information of each core: active and total times
+     * in ms since first boot.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *         the status.debugMessage must be populated with the human-readable
+     *         error message.
+     * @return cpuUsages If status code is SUCCESS, it's filled with the current
+     *         CPU usages. The order and number of CPUs in the list must be kept
+     *         the same regardless the number of calls to this method.
+     *
+     */
+    @callflow(next={"*"})
+    @entry
+    @exit
+    getCpuUsages() generates (ThermalStatus status, vec<CpuUsage> cpuUsages);
+
+    /*
+     * Retrieves the cooling devices information.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *         the status.debugMessage must be populated with the human-readable
+     *         error message.
+     * @return devices If status code is SUCCESS, it's filled with the current
+     *         cooling device information. The order of built-in cooling
+     *         devices in the list must be kept the same regardless the number
+     *         of calls to this method even if they go offline, if these devices
+     *         exist on boot. The method always returns and never removes from
+     *         the list such cooling devices.
+     *
+     */
+    @callflow(next={"*"})
+    @entry
+    @exit
+    getCoolingDevices()
+        generates (ThermalStatus status, vec<CoolingDevice> devices);
+
+};
diff --git a/thermal/1.0/default/Android.bp b/thermal/1.0/default/Android.bp
new file mode 100644
index 0000000..819f0b1
--- /dev/null
+++ b/thermal/1.0/default/Android.bp
@@ -0,0 +1,17 @@
+cc_library_shared {
+    name: "android.hardware.thermal@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Thermal.cpp"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.thermal@1.0",
+    ],
+}
diff --git a/thermal/1.0/default/Android.mk b/thermal/1.0/default/Android.mk
new file mode 100644
index 0000000..9039e9f
--- /dev/null
+++ b/thermal/1.0/default/Android.mk
@@ -0,0 +1,40 @@
+#
+# 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.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.thermal@1.0-service
+LOCAL_INIT_RC := android.hardware.thermal@1.0-service.rc
+LOCAL_SRC_FILES := \
+        service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+        liblog \
+        libcutils \
+        libdl \
+        libbase \
+        libutils \
+        libhardware_legacy \
+        libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+        libhwbinder \
+        libhidlbase \
+        libhidltransport \
+        android.hardware.thermal@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/thermal/1.0/default/Thermal.cpp b/thermal/1.0/default/Thermal.cpp
new file mode 100644
index 0000000..2dd0090
--- /dev/null
+++ b/thermal/1.0/default/Thermal.cpp
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.thermal@1.0-impl"
+
+#include <errno.h>
+#include <math.h>
+
+#include <vector>
+
+#include <log/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/thermal.h>
+
+#include "Thermal.h"
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_0 {
+namespace implementation {
+
+namespace {
+
+float finalizeTemperature(float temperature) {
+    return temperature == UNKNOWN_TEMPERATURE ? NAN : temperature;
+}
+
+}
+
+Thermal::Thermal(thermal_module_t* module) : mModule(module) {}
+
+// Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) {
+  ThermalStatus status;
+  status.code = ThermalStatusCode::SUCCESS;
+  hidl_vec<Temperature> temperatures;
+
+  if (!mModule || !mModule->getTemperatures) {
+    ALOGI("getTemperatures is not implemented in Thermal HAL.");
+    _hidl_cb(status, temperatures);
+    return Void();
+  }
+
+  ssize_t size = mModule->getTemperatures(mModule, nullptr, 0);
+  if (size >= 0) {
+    std::vector<temperature_t> list;
+    list.resize(size);
+    size = mModule->getTemperatures(mModule, list.data(), list.size());
+    if (size >= 0) {
+      temperatures.resize(list.size());
+      for (size_t i = 0; i < list.size(); ++i) {
+        switch (list[i].type) {
+          case DEVICE_TEMPERATURE_UNKNOWN:
+            temperatures[i].type = TemperatureType::UNKNOWN;
+            break;
+          case DEVICE_TEMPERATURE_CPU:
+            temperatures[i].type = TemperatureType::CPU;
+            break;
+          case DEVICE_TEMPERATURE_GPU:
+            temperatures[i].type = TemperatureType::GPU;
+            break;
+          case DEVICE_TEMPERATURE_BATTERY:
+            temperatures[i].type = TemperatureType::BATTERY;
+            break;
+          case DEVICE_TEMPERATURE_SKIN:
+            temperatures[i].type = TemperatureType::SKIN;
+            break;
+          default:
+            ALOGE("Unknown temperature %s type", list[i].name);
+            ;
+        }
+        temperatures[i].name = list[i].name;
+        temperatures[i].currentValue = finalizeTemperature(list[i].current_value);
+        temperatures[i].throttlingThreshold = finalizeTemperature(list[i].throttling_threshold);
+        temperatures[i].shutdownThreshold = finalizeTemperature(list[i].shutdown_threshold);
+        temperatures[i].vrThrottlingThreshold =
+                finalizeTemperature(list[i].vr_throttling_threshold);
+      }
+    }
+  }
+  if (size < 0) {
+    status.code = ThermalStatusCode::FAILURE;
+    status.debugMessage = strerror(-size);
+  }
+  _hidl_cb(status, temperatures);
+  return Void();
+}
+
+Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) {
+  ThermalStatus status;
+  hidl_vec<CpuUsage> cpuUsages;
+  status.code = ThermalStatusCode::SUCCESS;
+
+  if (!mModule || !mModule->getCpuUsages) {
+    ALOGI("getCpuUsages is not implemented in Thermal HAL");
+    _hidl_cb(status, cpuUsages);
+    return Void();
+  }
+
+  ssize_t size = mModule->getCpuUsages(mModule, nullptr);
+  if (size >= 0) {
+    std::vector<cpu_usage_t> list;
+    list.resize(size);
+    size = mModule->getCpuUsages(mModule, list.data());
+    if (size >= 0) {
+      list.resize(size);
+      cpuUsages.resize(size);
+      for (size_t i = 0; i < list.size(); ++i) {
+        cpuUsages[i].name = list[i].name;
+        cpuUsages[i].active = list[i].active;
+        cpuUsages[i].total = list[i].total;
+        cpuUsages[i].isOnline = list[i].is_online;
+      }
+    } else {
+      status.code = ThermalStatusCode::FAILURE;
+      status.debugMessage = strerror(-size);
+    }
+  }
+  if (size < 0) {
+    status.code = ThermalStatusCode::FAILURE;
+    status.debugMessage = strerror(-size);
+  }
+  _hidl_cb(status, cpuUsages);
+  return Void();
+}
+
+Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) {
+  ThermalStatus status;
+  status.code = ThermalStatusCode::SUCCESS;
+  hidl_vec<CoolingDevice> coolingDevices;
+
+  if (!mModule || !mModule->getCoolingDevices) {
+    ALOGI("getCoolingDevices is not implemented in Thermal HAL.");
+    _hidl_cb(status, coolingDevices);
+    return Void();
+  }
+
+  ssize_t size = mModule->getCoolingDevices(mModule, nullptr, 0);
+  if (size >= 0) {
+    std::vector<cooling_device_t> list;
+    list.resize(size);
+    size = mModule->getCoolingDevices(mModule, list.data(), list.size());
+    if (size >= 0) {
+      list.resize(size);
+      coolingDevices.resize(list.size());
+      for (size_t i = 0; i < list.size(); ++i) {
+        switch (list[i].type) {
+          case FAN_RPM:
+            coolingDevices[i].type = CoolingType::FAN_RPM;
+            break;
+          default:
+            ALOGE("Unknown cooling device %s type", list[i].name);
+        }
+        coolingDevices[i].name = list[i].name;
+        coolingDevices[i].currentValue = list[i].current_value;
+      }
+    }
+  }
+  if (size < 0) {
+    status.code = ThermalStatusCode::FAILURE;
+    status.debugMessage = strerror(-size);
+  }
+  _hidl_cb(status, coolingDevices);
+  return Void();
+}
+
+IThermal* HIDL_FETCH_IThermal(const char* /* name */) {
+  thermal_module_t* module;
+  status_t err = hw_get_module(THERMAL_HARDWARE_MODULE_ID,
+                               const_cast<hw_module_t const**>(
+                                   reinterpret_cast<hw_module_t**>(&module)));
+  if (err || !module) {
+    ALOGE("Couldn't load %s module (%s)", THERMAL_HARDWARE_MODULE_ID,
+          strerror(-err));
+  }
+
+  if (err == 0 && module->common.methods->open) {
+    struct hw_device_t* device;
+    err = module->common.methods->open(&module->common,
+                                       THERMAL_HARDWARE_MODULE_ID, &device);
+    if (err) {
+      ALOGE("Couldn't open %s module (%s)", THERMAL_HARDWARE_MODULE_ID,
+            strerror(-err));
+    } else {
+      return new Thermal(reinterpret_cast<thermal_module_t*>(device));
+    }
+  }
+  return new Thermal(module);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
diff --git a/thermal/1.0/default/Thermal.h b/thermal/1.0/default/Thermal.h
new file mode 100644
index 0000000..2e06289
--- /dev/null
+++ b/thermal/1.0/default/Thermal.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_THERMAL_V1_0_THERMAL_H
+#define ANDROID_HARDWARE_THERMAL_V1_0_THERMAL_H
+
+#include <android/hardware/thermal/1.0/IThermal.h>
+#include <hidl/Status.h>
+#include <hardware/thermal.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::thermal::V1_0::CoolingDevice;
+using ::android::hardware::thermal::V1_0::CpuUsage;
+using ::android::hardware::thermal::V1_0::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Thermal : public IThermal {
+    Thermal(thermal_module_t* module);
+    // Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+    Return<void> getTemperatures(getTemperatures_cb _hidl_cb)  override;
+    Return<void> getCpuUsages(getCpuUsages_cb _hidl_cb)  override;
+    Return<void> getCoolingDevices(getCoolingDevices_cb _hidl_cb)  override;
+    private:
+        thermal_module_t* mModule;
+};
+
+extern "C" IThermal* HIDL_FETCH_IThermal(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_THERMAL_V1_0_THERMAL_H
diff --git a/thermal/1.0/default/android.hardware.thermal@1.0-service.rc b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
new file mode 100644
index 0000000..cc7ba6a
--- /dev/null
+++ b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
@@ -0,0 +1,4 @@
+service thermal-hal-1-0 /system/bin/hw/android.hardware.thermal@1.0-service
+    class hal
+    user system
+    group system readproc
diff --git a/thermal/1.0/default/service.cpp b/thermal/1.0/default/service.cpp
new file mode 100644
index 0000000..ea86de4
--- /dev/null
+++ b/thermal/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.thermal@1.0-service"
+
+#include <android/hardware/thermal/1.0/IThermal.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::thermal::V1_0::IThermal;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IThermal>("thermal");
+}
diff --git a/thermal/1.0/types.hal b/thermal/1.0/types.hal
new file mode 100644
index 0000000..eb5d7c7
--- /dev/null
+++ b/thermal/1.0/types.hal
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.0;
+
+/** Device temperature types */
+@export
+enum TemperatureType : int32_t {
+    UNKNOWN = -1,
+    CPU = 0,
+    GPU = 1,
+    BATTERY = 2,
+    SKIN = 3,
+};
+
+enum CoolingType : uint32_t {
+    /** Fan cooling device speed in RPM. */
+    FAN_RPM = 0,
+};
+
+struct Temperature {
+    /**
+     * This temperature's type.
+     */
+    TemperatureType type;
+
+    /**
+     * Name of this temperature.
+     * All temperatures of the same "type" must have a different "name",
+     * e.g., cpu0, battery.
+     */
+    string name;
+
+    /**
+     * Current temperature in Celsius. If not available set by HAL to NAN.
+     * Current temperature can be in any units if type=UNKNOWN.
+     */
+    float currentValue;
+
+    /**
+     * Throttling temperature constant for this temperature.
+     * If not available, set by HAL to NAN.
+     */
+    float throttlingThreshold;
+
+    /**
+     * Shutdown temperature constant for this temperature.
+     * If not available, set by HAL to NAN.
+     */
+    float shutdownThreshold;
+
+    /**
+     * Threshold temperature above which the VR mode clockrate minimums cannot
+     * be maintained for this device.
+     * If not available, set by HAL to NAN.
+     */
+    float vrThrottlingThreshold;
+
+};
+
+struct CoolingDevice {
+    /**
+     * This cooling device type.
+     */
+    CoolingType type;
+
+    /**
+     * Name of this cooling device.
+     * All cooling devices of the same "type" must have a different "name".
+     */
+    string name;
+
+    /**
+     * Current cooling device value. Units depend on cooling device "type".
+     */
+    float currentValue;
+
+};
+
+struct CpuUsage {
+    /**
+     * Name of this CPU.
+     * All CPUs must have a different "name".
+     */
+    string name;
+
+    /**
+     * Active time since the last boot in ms.
+     */
+    uint64_t active;
+
+    /**
+     * Total time since the last boot in ms.
+     */
+    uint64_t total;
+
+    /**
+     * Is set to true when a core is online.
+     * If the core is offline, all other members except |name| should be ignored.
+     */
+    bool isOnline;
+
+};
+
+enum ThermalStatusCode : uint32_t {
+    /** No errors. */
+    SUCCESS = 0,
+    /** Unknown failure occured. */
+    FAILURE = 1
+};
+
+/**
+ * Generic structure to return the status of any thermal operation.
+ */
+struct ThermalStatus {
+    ThermalStatusCode code;
+
+    /**
+     * A specific error message to provide more information.
+     * This can be used for debugging purposes only.
+     */
+    string debugMessage;
+};
diff --git a/thermal/1.0/vts/Android.mk b/thermal/1.0/vts/Android.mk
new file mode 100644
index 0000000..60cc723
--- /dev/null
+++ b/thermal/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/Thermal.vts b/thermal/1.0/vts/Thermal.vts
new file mode 100644
index 0000000..e76d943
--- /dev/null
+++ b/thermal/1.0/vts/Thermal.vts
@@ -0,0 +1,82 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IThermal"
+
+package: "android.hardware.thermal"
+
+import: "android.hardware.thermal@1.0::types"
+
+interface: {
+    api: {
+        name: "getTemperatures"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::thermal::V1_0::ThermalStatus"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::thermal::V1_0::Temperature"
+            }
+        }
+        callflow: {
+            next: "*"
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "getCpuUsages"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::thermal::V1_0::ThermalStatus"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::thermal::V1_0::CpuUsage"
+            }
+        }
+        callflow: {
+            next: "*"
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "getCoolingDevices"
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::thermal::V1_0::ThermalStatus"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::thermal::V1_0::CoolingDevice"
+            }
+        }
+        callflow: {
+            next: "*"
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+}
diff --git a/thermal/1.0/vts/functional/Android.bp b/thermal/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..bef7bc2
--- /dev/null
+++ b/thermal/1.0/vts/functional/Android.bp
@@ -0,0 +1,42 @@
+//
+// 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_test {
+    name: "thermal_hidl_hal_test",
+    gtest: true,
+    srcs: ["thermal_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libnativehelper",
+        "libutils",
+        "android.hardware.thermal@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "--coverage",
+        "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
+
diff --git a/thermal/1.0/vts/functional/Android.mk b/thermal/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
new file mode 100644
index 0000000..d922169
--- /dev/null
+++ b/thermal/1.0/vts/functional/thermal_hidl_hal_test.cpp
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+
+#include <algorithm>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "thermal_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/thermal/1.0/IThermal.h>
+#include <android/hardware/thermal/1.0/types.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::thermal::V1_0::CoolingDevice;
+using ::android::hardware::thermal::V1_0::CpuUsage;
+using ::android::hardware::thermal::V1_0::IThermal;
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+#define THERMAL_SERVICE_NAME "thermal"
+#define MONITORING_OPERATION_NUMBER 10
+
+#define MAX_DEVICE_TEMPERATURE 200
+#define MAX_FAN_SPEED 20000
+
+// The main test class for THERMAL HIDL HAL.
+class ThermalHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    thermal_ = IThermal::getService(THERMAL_SERVICE_NAME, false);
+    ASSERT_NE(thermal_, nullptr);
+    baseSize_ = 0;
+    names_.clear();
+  }
+
+  virtual void TearDown() override {}
+
+ protected:
+  // Check validity of temperatures returned by Thremal HAL.
+  void checkTemperatures(const hidl_vec<Temperature> temperatures) {
+    size_t size = temperatures.size();
+    EXPECT_LE(baseSize_, size);
+
+    for (size_t i = 0; i < size; ++i) {
+      checkDeviceTemperature(temperatures[i]);
+      if (i < baseSize_) {
+        EXPECT_EQ(names_[i], temperatures[i].name.c_str());
+      } else {
+        // Names must be unique.
+        EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
+                                          temperatures[i].name.c_str()));
+        names_.push_back(temperatures[i].name);
+      }
+    }
+    baseSize_ = size;
+  }
+
+  // Check validity of CPU usages returned by Thermal HAL.
+  void checkCpuUsages(const hidl_vec<CpuUsage>& cpuUsages) {
+    size_t size = cpuUsages.size();
+    // A number of CPU's does not change.
+    if (baseSize_ != 0) EXPECT_EQ(baseSize_, size);
+
+    for (size_t i = 0; i < size; ++i) {
+      checkCpuUsage(cpuUsages[i]);
+      if (i < baseSize_) {
+        EXPECT_EQ(names_[i], cpuUsages[i].name.c_str());
+      } else {
+        // Names must be unique.
+        EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
+                                          cpuUsages[i].name.c_str()));
+        names_.push_back(cpuUsages[i].name);
+      }
+    }
+    baseSize_ = size;
+  }
+
+  // Check validity of cooling devices information returned by Thermal HAL.
+  void checkCoolingDevices(const hidl_vec<CoolingDevice> coolingDevices) {
+    size_t size = coolingDevices.size();
+    EXPECT_LE(baseSize_, size);
+
+    for (size_t i = 0; i < size; ++i) {
+      checkCoolingDevice(coolingDevices[i]);
+      if (i < baseSize_) {
+        EXPECT_EQ(names_[i], coolingDevices[i].name.c_str());
+      } else {
+        // Names must be unique.
+        EXPECT_EQ(names_.end(), std::find(names_.begin(), names_.end(),
+                                          coolingDevices[i].name.c_str()));
+        names_.push_back(coolingDevices[i].name);
+      }
+    }
+    baseSize_ = size;
+  }
+
+  sp<IThermal> thermal_;
+
+ private:
+  // Check validity of temperature returned by Thermal HAL.
+  void checkDeviceTemperature(const Temperature& temperature) {
+    // .currentValue of known type is in Celsius and must be reasonable.
+    EXPECT_TRUE(temperature.type == TemperatureType::UNKNOWN ||
+                std::abs(temperature.currentValue) < MAX_DEVICE_TEMPERATURE ||
+                isnan(temperature.currentValue));
+
+    // .name must not be empty.
+    EXPECT_LT(0u, temperature.name.size());
+
+    // .currentValue must not exceed .shutdwonThreshold if defined.
+    EXPECT_TRUE(temperature.currentValue < temperature.shutdownThreshold ||
+                isnan(temperature.currentValue) || isnan(temperature.shutdownThreshold));
+
+    // .throttlingThreshold must not exceed .shutdownThreshold if defined.
+    EXPECT_TRUE(temperature.throttlingThreshold < temperature.shutdownThreshold ||
+                isnan(temperature.throttlingThreshold) || isnan(temperature.shutdownThreshold));
+  }
+
+  // Check validity of CPU usage returned by Thermal HAL.
+  void checkCpuUsage(const CpuUsage& cpuUsage) {
+    // .active must be less than .total if CPU is online.
+    EXPECT_TRUE(!cpuUsage.isOnline ||
+                (cpuUsage.active >= 0 && cpuUsage.total >= 0 &&
+                 cpuUsage.total >= cpuUsage.active));
+
+    // .name must be not empty.
+    EXPECT_LT(0u, cpuUsage.name.size());
+  }
+
+  // Check validity of a cooling device information returned by Thermal HAL.
+  void checkCoolingDevice(const CoolingDevice& coolingDevice) {
+    EXPECT_LE(0, coolingDevice.currentValue);
+    EXPECT_GT(MAX_FAN_SPEED, coolingDevice.currentValue);
+    EXPECT_LT(0u, coolingDevice.name.size());
+  }
+
+  size_t baseSize_;
+  std::vector<hidl_string> names_;
+};
+
+// Sanity test for Thermal::getTemperatures().
+TEST_F(ThermalHidlTest, TemperatureTest) {
+  hidl_vec<Temperature> passed;
+  for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
+    thermal_->getTemperatures(
+        [&passed](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+          EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+          passed = temperatures;
+        });
+
+    checkTemperatures(passed);
+    sleep(1);
+  }
+}
+
+// Sanity test for Thermal::getCpuUsages().
+TEST_F(ThermalHidlTest, CpuUsageTest) {
+  hidl_vec<CpuUsage> passed;
+  for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
+    thermal_->getCpuUsages(
+        [&passed](ThermalStatus status, hidl_vec<CpuUsage> cpuUsages) {
+          EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+          passed = cpuUsages;
+        });
+
+    checkCpuUsages(passed);
+    sleep(1);
+  }
+}
+
+// Sanity test for Thermal::getCoolingDevices().
+TEST_F(ThermalHidlTest, CoolingDeviceTest) {
+  hidl_vec<CoolingDevice> passed;
+  for (size_t i = 0; i < MONITORING_OPERATION_NUMBER; ++i) {
+    thermal_->getCoolingDevices([&passed](
+        ThermalStatus status, hidl_vec<CoolingDevice> coolingDevices) {
+      EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+      passed = coolingDevices;
+    });
+
+    checkCoolingDevices(passed);
+    sleep(1);
+  }
+}
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/thermal/1.0/vts/functional/vts/Android.mk b/thermal/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/vts/testcases/Android.mk b/thermal/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/Android.mk b/thermal/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/Android.mk b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/__init__.py b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/__init__.py
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/Android.mk b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/__init__.py b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/__init__.py
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/Android.mk b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/Android.mk
new file mode 100644
index 0000000..1c3ceb3
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ThermalHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/thermal/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..169264d
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VIBRATOR HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="ThermalHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/thermal_hidl_hal_test/thermal_hidl_hal_test,
+            _64bit::DATA/nativetest64/thermal_hidl_hal_test/thermal_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+    </test>
+</configuration>
+
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/Android.mk b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..1f937fa
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ThermalHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/thermal/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/AndroidTest.xml b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..46ae05a
--- /dev/null
+++ b/thermal/1.0/vts/functional/vts/testcases/hal/thermal/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS THERMAL HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="ThermalHidlTargetProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/thermal_hidl_hal_test/thermal_hidl_hal_test,
+            _64bit::DATA/nativetest64/thermal_hidl_hal_test/thermal_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="5m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
+
diff --git a/thermal/1.0/vts/types.vts b/thermal/1.0/vts/types.vts
new file mode 100644
index 0000000..1e60f48
--- /dev/null
+++ b/thermal/1.0/vts/types.vts
@@ -0,0 +1,157 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.thermal"
+
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::TemperatureType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            uint32_t: 1000
+        }
+        enumerator: "CPU"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "GPU"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "BATTERY"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "SKIN"
+        scalar_value: {
+            uint32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::CoolingType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "FAN_RPM"
+        scalar_value: {
+            uint32_t: 0
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::Temperature"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::thermal::V1_0::TemperatureType"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "currentValue"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "throttlingThreshold"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "shutdownThreshold"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "vrThrottlingThreshold"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::CoolingDevice"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::thermal::V1_0::CoolingType"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "currentValue"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::CpuUsage"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "active"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "total"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+    struct_value: {
+        name: "isOnline"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::ThermalStatusCode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "FAILURE"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::thermal::V1_0::ThermalStatus"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "code"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::thermal::V1_0::ThermalStatusCode"
+    }
+    struct_value: {
+        name: "debugMessage"
+        type: TYPE_STRING
+    }
+}
+
diff --git a/thermal/Android.bp b/thermal/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/thermal/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/tv/Android.bp b/tv/Android.bp
new file mode 100644
index 0000000..5ad82f4
--- /dev/null
+++ b/tv/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "cec/1.0",
+    "input/1.0",
+]
diff --git a/tv/cec/1.0/Android.bp b/tv/cec/1.0/Android.bp
new file mode 100644
index 0000000..21233ab
--- /dev/null
+++ b/tv/cec/1.0/Android.bp
@@ -0,0 +1,216 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.tv.cec@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0",
+    srcs: [
+        "types.hal",
+        "IHdmiCec.hal",
+        "IHdmiCecCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/types.cpp",
+        "android/hardware/tv/cec/1.0/HdmiCecAll.cpp",
+        "android/hardware/tv/cec/1.0/HdmiCecCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0",
+    srcs: [
+        "types.hal",
+        "IHdmiCec.hal",
+        "IHdmiCecCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/types.h",
+        "android/hardware/tv/cec/1.0/IHdmiCec.h",
+        "android/hardware/tv/cec/1.0/IHwHdmiCec.h",
+        "android/hardware/tv/cec/1.0/BnHwHdmiCec.h",
+        "android/hardware/tv/cec/1.0/BpHwHdmiCec.h",
+        "android/hardware/tv/cec/1.0/BsHdmiCec.h",
+        "android/hardware/tv/cec/1.0/IHdmiCecCallback.h",
+        "android/hardware/tv/cec/1.0/IHwHdmiCecCallback.h",
+        "android/hardware/tv/cec/1.0/BnHwHdmiCecCallback.h",
+        "android/hardware/tv/cec/1.0/BpHwHdmiCecCallback.h",
+        "android/hardware/tv/cec/1.0/BsHdmiCecCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.cec@1.0",
+    generated_sources: ["android.hardware.tv.cec@1.0_genc++"],
+    generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "types.hal",
+        "IHdmiCec.hal",
+        "IHdmiCecCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/types.vts.cpp",
+        "android/hardware/tv/cec/1.0/HdmiCec.vts.cpp",
+        "android/hardware/tv/cec/1.0/HdmiCecCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "types.hal",
+        "IHdmiCec.hal",
+        "IHdmiCecCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/types.vts.h",
+        "android/hardware/tv/cec/1.0/HdmiCec.vts.h",
+        "android/hardware/tv/cec/1.0/HdmiCecCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.cec.vts.driver@1.0",
+    generated_sources: ["android.hardware.tv.cec.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.tv.cec.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.cec.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.cec@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "IHdmiCec.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/HdmiCec.vts.cpp",
+        "android/hardware/tv/cec/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "IHdmiCec.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/HdmiCec.vts.h",
+        "android/hardware/tv/cec/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler",
+    generated_sources: ["android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.cec@1.0-IHdmiCec-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.cec@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "IHdmiCecCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/HdmiCecCallback.vts.cpp",
+        "android/hardware/tv/cec/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.cec@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/tv/cec/1.0/ $(genDir)/android/hardware/tv/cec/1.0/",
+    srcs: [
+        "IHdmiCecCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/cec/1.0/HdmiCecCallback.vts.h",
+        "android/hardware/tv/cec/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler",
+    generated_sources: ["android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.cec@1.0-IHdmiCecCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.cec@1.0",
+    ],
+}
diff --git a/tv/cec/1.0/Android.mk b/tv/cec/1.0/Android.mk
new file mode 100644
index 0000000..efa71a1
--- /dev/null
+++ b/tv/cec/1.0/Android.mk
@@ -0,0 +1,582 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tv.cec@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (AbortReason)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/AbortReason.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.AbortReason
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecDeviceType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecDeviceType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecDeviceType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecLogicalAddress)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecLogicalAddress.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecLogicalAddress
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecMessage)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecMessage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecMessage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecMessageType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HdmiPortInfo)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HdmiPortInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HdmiPortInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HdmiPortType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HdmiPortType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HdmiPortType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HotplugEvent)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HotplugEvent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HotplugEvent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MaxLength)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/MaxLength.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.MaxLength
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (OptionKey)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/OptionKey.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.OptionKey
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SendMessageResult)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/SendMessageResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.SendMessageResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHdmiCec.hal
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/IHdmiCec.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHdmiCec.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::IHdmiCec
+
+$(GEN): $(LOCAL_PATH)/IHdmiCec.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHdmiCecCallback.hal
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/IHdmiCecCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::IHdmiCecCallback
+
+$(GEN): $(LOCAL_PATH)/IHdmiCecCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tv.cec@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (AbortReason)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/AbortReason.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.AbortReason
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecDeviceType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecDeviceType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecDeviceType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecLogicalAddress)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecLogicalAddress.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecLogicalAddress
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecMessage)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecMessage.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecMessage
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CecMessageType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/CecMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.CecMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HdmiPortInfo)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HdmiPortInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HdmiPortInfo
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HdmiPortType)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HdmiPortType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HdmiPortType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (HotplugEvent)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/HotplugEvent.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.HotplugEvent
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (MaxLength)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/MaxLength.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.MaxLength
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (OptionKey)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/OptionKey.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.OptionKey
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Result)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/Result.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.Result
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SendMessageResult)
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/SendMessageResult.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::types.SendMessageResult
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHdmiCec.hal
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/IHdmiCec.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHdmiCec.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::IHdmiCec
+
+$(GEN): $(LOCAL_PATH)/IHdmiCec.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IHdmiCecCallback.hal
+#
+GEN := $(intermediates)/android/hardware/tv/cec/V1_0/IHdmiCecCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IHdmiCecCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tv.cec@1.0::IHdmiCecCallback
+
+$(GEN): $(LOCAL_PATH)/IHdmiCecCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tv/cec/1.0/IHdmiCec.hal b/tv/cec/1.0/IHdmiCec.hal
new file mode 100644
index 0000000..e8db265
--- /dev/null
+++ b/tv/cec/1.0/IHdmiCec.hal
@@ -0,0 +1,166 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.cec@1.0;
+
+import IHdmiCecCallback;
+
+/*
+ * HDMI-CEC HAL interface definition.
+ */
+interface IHdmiCec {
+    /*
+     * Passes the logical address that must be used in this system.
+     *
+     * HAL must use it to configure the hardware so that the CEC commands
+     * addressed the given logical address can be filtered in. This method must
+     * be able to be called as many times as necessary in order to support
+     * multiple logical devices.
+     *
+     * @param addr Logical address that must be used in this system. It must be
+     *        in the range of valid logical addresses for the call to succeed.
+     * @return result Result status of the operation. SUCCESS if successful,
+     *         FAILURE_INVALID_ARGS if the given logical address is invalid,
+     *         FAILURE_BUSY if device or resource is busy
+     */
+    @callflow(next={"*"})
+    addLogicalAddress(CecLogicalAddress addr) generates (Result result);
+
+    /*
+     * Clears all the logical addresses.
+     *
+     * It is used when the system doesn't need to process CEC command any more,
+     * hence to tell HAL to stop receiving commands from the CEC bus, and change
+     * the state back to the beginning.
+     */
+    @callflow(next="addLogicalAddress")
+    @exit
+    clearLogicalAddress();
+
+    /*
+     * Gets the CEC physical address.
+     *
+     * The physical address depends on the topology of the network formed by
+     * connected HDMI devices. It is therefore likely to change if the cable is
+     * plugged off and on again. It is advised to call getPhysicalAddress to get
+     * the updated address when hot plug event takes place.
+     *
+     * @return result Result status of the operation. SUCCESS if successful,
+     *         FAILURE_INVALID_STATE if HAL cannot retrieve the physical
+     *         address.
+     * @return addr Physical address of this device.
+     */
+    @callflow(next="*")
+    getPhysicalAddress() generates (Result result, uint16_t addr);
+
+    /*
+     * Transmits HDMI-CEC message to other HDMI device.
+     *
+     * The method must be designed to return in a certain amount of time and not
+     * hanging forever which may happen if CEC signal line is pulled low for
+     * some reason.
+     *
+     * It must try retransmission at least once as specified in the section '7.1
+     * Frame Re-transmissions' of the CEC Spec 1.4b.
+     *
+     * @param message CEC message to be sent to other HDMI device.
+     * @return result Result status of the operation. SUCCESS if successful,
+     *         NACK if the sent message is not acknowledged,
+     *         BUSY if the CEC bus is busy.
+     */
+    @callflow(next="*")
+    sendMessage(CecMessage message) generates (SendMessageResult result);
+
+    /*
+     * Sets a callback that HDMI-CEC HAL must later use for incoming CEC
+     * messages or internal HDMI events.
+     *
+     * @param callback Callback object to pass hdmi events to the system. The
+     *        previously registered callback must be replaced with this one.
+     */
+    @callflow(next={"addLogicalAddress"})
+    @entry
+    setCallback(IHdmiCecCallback callback);
+
+    /*
+     * Returns the CEC version supported by underlying hardware.
+     *
+     * @return version the CEC version supported by underlying hardware.
+     */
+    @callflow(next={"*"})
+    getCecVersion() generates (int32_t version);
+
+    /*
+     * Gets the identifier of the vendor.
+     *
+     * @return vendorId Identifier of the vendor that is the 24-bit unique
+     *         company ID obtained from the IEEE Registration Authority
+     *         Committee (RAC). The upper 8 bits must be 0.
+     */
+    @callflow(next={"*"})
+    getVendorId() generates (uint32_t vendorId);
+
+    /*
+     * Gets the hdmi port information of underlying hardware.
+     *
+     * @return infos The list of HDMI port information
+     */
+    @callflow(next={"*"})
+    getPortInfo() generates (vec<HdmiPortInfo> infos);
+
+    /*
+     * Sets flags controlling the way HDMI-CEC service works down to HAL
+     * implementation. Those flags must be used in case the feature needs update
+     * in HAL itself, firmware or microcontroller.
+     *
+     * @param key The key of the option to be updated with a new value.
+     * @param value Value to be set.
+     */
+    @callflow(next="*")
+    setOption(OptionKey key, bool value);
+
+    /*
+     * Passes the updated language information of Android system. Contains
+     * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to
+     * respond to <Get Menu Language> while in standby mode.
+     *
+     * @param language Three-letter code defined in ISO/FDIS 639-2. Must be
+     *        lowercase letters. (e.g., eng for English)
+     */
+    @callflow(next="*")
+    setLanguage(string language);
+
+    /*
+     * Configures ARC circuit in the hardware logic to start or stop the
+     * feature.
+     *
+     * @param portId Port id to be configured.
+     * @param enable Flag must be either true to start the feature or false to
+     *        stop it.
+     */
+    @callflow(next="*")
+    enableAudioReturnChannel(int32_t portId, bool enable);
+
+    /*
+     * Gets the connection status of the specified port.
+     *
+     * @param portId Port id to be inspected for the connection status.
+     * @return status True if a device is connected, otherwise false. The HAL
+     *         must watch for +5V power signal to determine the status.
+     */
+    @callflow(next="*")
+    isConnected(int32_t portId) generates (bool status);
+};
diff --git a/tv/cec/1.0/IHdmiCecCallback.hal b/tv/cec/1.0/IHdmiCecCallback.hal
new file mode 100644
index 0000000..4a9d28f
--- /dev/null
+++ b/tv/cec/1.0/IHdmiCecCallback.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.cec@1.0;
+
+interface IHdmiCecCallback {
+    /*
+     * The callback function that must be called by HAL implementation to notify
+     * the system of new CEC message arrival.
+     */
+    oneway onCecMessage(CecMessage message);
+
+    /*
+     * The callback function that must be called by HAL implementation to notify
+     * the system of new hotplug event.
+     */
+    oneway onHotplugEvent(HotplugEvent event);
+};
diff --git a/tv/cec/1.0/default/Android.mk b/tv/cec/1.0/default/Android.mk
new file mode 100644
index 0000000..492fc8c
--- /dev/null
+++ b/tv/cec/1.0/default/Android.mk
@@ -0,0 +1,44 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tv.cec@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    HdmiCec.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libbase \
+    libutils \
+    libhardware \
+    android.hardware.tv.cec@1.0 \
+
+include $(BUILD_SHARED_LIBRARY)
+
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.tv.cec@1.0-service
+LOCAL_INIT_RC := android.hardware.tv.cec@1.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.tv.cec@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/tv/cec/1.0/default/HdmiCec.cpp b/tv/cec/1.0/default/HdmiCec.cpp
new file mode 100644
index 0000000..ebe2681
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCec.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.cec@1.0-impl"
+#include <android-base/logging.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+#include "HdmiCec.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+static_assert(CEC_DEVICE_INACTIVE == static_cast<int>(CecDeviceType::INACTIVE),
+        "CecDeviceType::INACTIVE must match legacy value.");
+static_assert(CEC_DEVICE_TV == static_cast<int>(CecDeviceType::TV),
+        "CecDeviceType::TV must match legacy value.");
+static_assert(CEC_DEVICE_RECORDER == static_cast<int>(CecDeviceType::RECORDER),
+        "CecDeviceType::RECORDER must match legacy value.");
+static_assert(CEC_DEVICE_TUNER == static_cast<int>(CecDeviceType::TUNER),
+        "CecDeviceType::TUNER must match legacy value.");
+static_assert(CEC_DEVICE_PLAYBACK == static_cast<int>(CecDeviceType::PLAYBACK),
+        "CecDeviceType::PLAYBACK must match legacy value.");
+static_assert(CEC_DEVICE_AUDIO_SYSTEM == static_cast<int>(CecDeviceType::AUDIO_SYSTEM),
+        "CecDeviceType::AUDIO_SYSTEM must match legacy value.");
+static_assert(CEC_DEVICE_MAX == static_cast<int>(CecDeviceType::MAX),
+        "CecDeviceType::MAX must match legacy value.");
+
+static_assert(CEC_ADDR_TV == static_cast<int>(CecLogicalAddress::TV),
+        "CecLogicalAddress::TV must match legacy value.");
+static_assert(CEC_ADDR_RECORDER_1 == static_cast<int>(CecLogicalAddress::RECORDER_1),
+        "CecLogicalAddress::RECORDER_1 must match legacy value.");
+static_assert(CEC_ADDR_RECORDER_2 == static_cast<int>(CecLogicalAddress::RECORDER_2),
+        "CecLogicalAddress::RECORDER_2 must match legacy value.");
+static_assert(CEC_ADDR_TUNER_1 == static_cast<int>(CecLogicalAddress::TUNER_1),
+        "CecLogicalAddress::TUNER_1 must match legacy value.");
+static_assert(CEC_ADDR_PLAYBACK_1 == static_cast<int>(CecLogicalAddress::PLAYBACK_1),
+        "CecLogicalAddress::PLAYBACK_1 must match legacy value.");
+static_assert(CEC_ADDR_AUDIO_SYSTEM == static_cast<int>(CecLogicalAddress::AUDIO_SYSTEM),
+        "CecLogicalAddress::AUDIO_SYSTEM must match legacy value.");
+static_assert(CEC_ADDR_TUNER_2 == static_cast<int>(CecLogicalAddress::TUNER_2),
+        "CecLogicalAddress::TUNER_2 must match legacy value.");
+static_assert(CEC_ADDR_TUNER_3 == static_cast<int>(CecLogicalAddress::TUNER_3),
+        "CecLogicalAddress::TUNER_3 must match legacy value.");
+static_assert(CEC_ADDR_PLAYBACK_2 == static_cast<int>(CecLogicalAddress::PLAYBACK_2),
+        "CecLogicalAddress::PLAYBACK_2 must match legacy value.");
+static_assert(CEC_ADDR_RECORDER_3 == static_cast<int>(CecLogicalAddress::RECORDER_3),
+        "CecLogicalAddress::RECORDER_3 must match legacy value.");
+static_assert(CEC_ADDR_TUNER_4 == static_cast<int>(CecLogicalAddress::TUNER_4),
+        "CecLogicalAddress::TUNER_4 must match legacy value.");
+static_assert(CEC_ADDR_PLAYBACK_3 == static_cast<int>(CecLogicalAddress::PLAYBACK_3),
+        "CecLogicalAddress::PLAYBACK_3 must match legacy value.");
+static_assert(CEC_ADDR_FREE_USE == static_cast<int>(CecLogicalAddress::FREE_USE),
+        "CecLogicalAddress::FREE_USE must match legacy value.");
+static_assert(CEC_ADDR_UNREGISTERED == static_cast<int>(CecLogicalAddress::UNREGISTERED),
+        "CecLogicalAddress::UNREGISTERED must match legacy value.");
+static_assert(CEC_ADDR_BROADCAST == static_cast<int>(CecLogicalAddress::BROADCAST),
+        "CecLogicalAddress::BROADCAST must match legacy value.");
+
+static_assert(CEC_MESSAGE_FEATURE_ABORT == static_cast<int>(CecMessageType::FEATURE_ABORT),
+        "CecMessageType::FEATURE_ABORT must match legacy value.");
+static_assert(CEC_MESSAGE_IMAGE_VIEW_ON == static_cast<int>(CecMessageType::IMAGE_VIEW_ON),
+        "CecMessageType::IMAGE_VIEW_ON must match legacy value.");
+static_assert(CEC_MESSAGE_TUNER_STEP_INCREMENT == static_cast<int>(
+        CecMessageType::TUNER_STEP_INCREMENT),
+        "CecMessageType::TUNER_STEP_INCREMENT must match legacy value.");
+static_assert(CEC_MESSAGE_TUNER_STEP_DECREMENT == static_cast<int>(
+        CecMessageType::TUNER_STEP_DECREMENT),
+        "CecMessageType::TUNER_STEP_DECREMENT must match legacy value.");
+static_assert(CEC_MESSAGE_TUNER_DEVICE_STATUS == static_cast<int>(
+        CecMessageType::TUNER_DEVICE_STATUS),
+        "CecMessageType::TUNER_DEVICE_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_TUNER_DEVICE_STATUS == static_cast<int>(
+        CecMessageType::GIVE_TUNER_DEVICE_STATUS),
+        "CecMessageType::GIVE_TUNER_DEVICE_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_RECORD_ON == static_cast<int>(CecMessageType::RECORD_ON),
+        "CecMessageType::RECORD_ON must match legacy value.");
+static_assert(CEC_MESSAGE_RECORD_STATUS == static_cast<int>(CecMessageType::RECORD_STATUS),
+        "CecMessageType::RECORD_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_RECORD_OFF == static_cast<int>(CecMessageType::RECORD_OFF),
+        "CecMessageType::RECORD_OFF must match legacy value.");
+static_assert(CEC_MESSAGE_TEXT_VIEW_ON == static_cast<int>(CecMessageType::TEXT_VIEW_ON),
+        "CecMessageType::TEXT_VIEW_ON must match legacy value.");
+static_assert(CEC_MESSAGE_RECORD_TV_SCREEN == static_cast<int>(CecMessageType::RECORD_TV_SCREEN),
+        "CecMessageType::RECORD_TV_SCREEN must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_DECK_STATUS == static_cast<int>(CecMessageType::GIVE_DECK_STATUS),
+        "CecMessageType::GIVE_DECK_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_STANDBY == static_cast<int>(CecMessageType::STANDBY),
+        "CecMessageType::STANDBY must match legacy value.");
+static_assert(CEC_MESSAGE_PLAY == static_cast<int>(CecMessageType::PLAY),
+        "CecMessageType::PLAY must match legacy value.");
+static_assert(CEC_MESSAGE_DECK_CONTROL == static_cast<int>(CecMessageType::DECK_CONTROL),
+        "CecMessageType::DECK_CONTROL must match legacy value.");
+static_assert(CEC_MESSAGE_TIMER_CLEARED_STATUS == static_cast<int>(
+        CecMessageType::TIMER_CLEARED_STATUS),
+        "CecMessageType::TIMER_CLEARED_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_USER_CONTROL_PRESSED == static_cast<int>(
+        CecMessageType::USER_CONTROL_PRESSED),
+        "CecMessageType::USER_CONTROL_PRESSED must match legacy value.");
+static_assert(CEC_MESSAGE_USER_CONTROL_RELEASED == static_cast<int>(
+        CecMessageType::USER_CONTROL_RELEASED),
+        "CecMessageType::USER_CONTROL_RELEASED must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_OSD_NAME == static_cast<int>(CecMessageType::GIVE_OSD_NAME),
+        "CecMessageType::GIVE_OSD_NAME must match legacy value.");
+static_assert(CEC_MESSAGE_SET_OSD_NAME == static_cast<int>(CecMessageType::SET_OSD_NAME),
+        "CecMessageType::SET_OSD_NAME must match legacy value.");
+static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_REQUEST == static_cast<int>(
+        CecMessageType::SYSTEM_AUDIO_MODE_REQUEST),
+        "CecMessageType::SYSTEM_AUDIO_MODE_REQUEST must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_AUDIO_STATUS == static_cast<int>(CecMessageType::GIVE_AUDIO_STATUS),
+        "CecMessageType::GIVE_AUDIO_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_SET_SYSTEM_AUDIO_MODE == static_cast<int>(
+        CecMessageType::SET_SYSTEM_AUDIO_MODE),
+        "CecMessageType::SET_SYSTEM_AUDIO_MODE must match legacy value.");
+static_assert(CEC_MESSAGE_REPORT_AUDIO_STATUS == static_cast<int>(
+        CecMessageType::REPORT_AUDIO_STATUS),
+        "CecMessageType::REPORT_AUDIO_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_SYSTEM_AUDIO_MODE_STATUS == static_cast<int>(
+        CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS),
+        "CecMessageType::GIVE_SYSTEM_AUDIO_MODE_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_SYSTEM_AUDIO_MODE_STATUS == static_cast<int>(
+        CecMessageType::SYSTEM_AUDIO_MODE_STATUS),
+        "CecMessageType::SYSTEM_AUDIO_MODE_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_ROUTING_CHANGE == static_cast<int>(CecMessageType::ROUTING_CHANGE),
+        "CecMessageType::ROUTING_CHANGE must match legacy value.");
+static_assert(CEC_MESSAGE_ROUTING_INFORMATION == static_cast<int>(
+        CecMessageType::ROUTING_INFORMATION),
+        "CecMessageType::ROUTING_INFORMATION must match legacy value.");
+static_assert(CEC_MESSAGE_ACTIVE_SOURCE == static_cast<int>(CecMessageType::ACTIVE_SOURCE),
+        "CecMessageType::ACTIVE_SOURCE must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS == static_cast<int>(
+        CecMessageType::GIVE_PHYSICAL_ADDRESS),
+        "CecMessageType::GIVE_PHYSICAL_ADDRESS must match legacy value.");
+static_assert(CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS == static_cast<int>(
+        CecMessageType::REPORT_PHYSICAL_ADDRESS),
+        "CecMessageType::REPORT_PHYSICAL_ADDRESS must match legacy value.");
+static_assert(CEC_MESSAGE_REQUEST_ACTIVE_SOURCE == static_cast<int>(
+        CecMessageType::REQUEST_ACTIVE_SOURCE),
+        "CecMessageType::REQUEST_ACTIVE_SOURCE must match legacy value.");
+static_assert(CEC_MESSAGE_SET_STREAM_PATH == static_cast<int>(CecMessageType::SET_STREAM_PATH),
+        "CecMessageType::SET_STREAM_PATH must match legacy value.");
+static_assert(CEC_MESSAGE_DEVICE_VENDOR_ID == static_cast<int>(CecMessageType::DEVICE_VENDOR_ID),
+        "CecMessageType::DEVICE_VENDOR_ID must match legacy value.");
+static_assert(CEC_MESSAGE_VENDOR_COMMAND == static_cast<int>(CecMessageType::VENDOR_COMMAND),
+        "CecMessageType::VENDOR_COMMAND must match legacy value.");
+static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_DOWN == static_cast<int>(
+        CecMessageType::VENDOR_REMOTE_BUTTON_DOWN),
+        "CecMessageType::VENDOR_REMOTE_BUTTON_DOWN must match legacy value.");
+static_assert(CEC_MESSAGE_VENDOR_REMOTE_BUTTON_UP == static_cast<int>(
+        CecMessageType::VENDOR_REMOTE_BUTTON_UP),
+        "CecMessageType::VENDOR_REMOTE_BUTTON_UP must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_DEVICE_VENDOR_ID == static_cast<int>(
+        CecMessageType::GIVE_DEVICE_VENDOR_ID),
+        "CecMessageType::GIVE_DEVICE_VENDOR_ID must match legacy value.");
+static_assert(CEC_MESSAGE_MENU_REQUEST == static_cast<int>(CecMessageType::MENU_REQUEST),
+        "CecMessageType::MENU_REQUEST must match legacy value.");
+static_assert(CEC_MESSAGE_MENU_STATUS == static_cast<int>(CecMessageType::MENU_STATUS),
+        "CecMessageType::MENU_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_GIVE_DEVICE_POWER_STATUS == static_cast<int>(
+        CecMessageType::GIVE_DEVICE_POWER_STATUS),
+        "CecMessageType::GIVE_DEVICE_POWER_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_REPORT_POWER_STATUS == static_cast<int>(
+        CecMessageType::REPORT_POWER_STATUS),
+        "CecMessageType::REPORT_POWER_STATUS must match legacy value.");
+static_assert(CEC_MESSAGE_GET_MENU_LANGUAGE == static_cast<int>(CecMessageType::GET_MENU_LANGUAGE),
+        "CecMessageType::GET_MENU_LANGUAGE must match legacy value.");
+static_assert(CEC_MESSAGE_SELECT_ANALOG_SERVICE == static_cast<int>(
+        CecMessageType::SELECT_ANALOG_SERVICE),
+        "CecMessageType::SELECT_ANALOG_SERVICE must match legacy value.");
+static_assert(CEC_MESSAGE_SELECT_DIGITAL_SERVICE == static_cast<int>(
+        CecMessageType::SELECT_DIGITAL_SERVICE),
+        "CecMessageType::SELECT_DIGITAL_SERVICE must match legacy value.");
+static_assert(CEC_MESSAGE_SET_DIGITAL_TIMER == static_cast<int>(CecMessageType::SET_DIGITAL_TIMER),
+        "CecMessageType::SET_DIGITAL_TIMER must match legacy value.");
+static_assert(CEC_MESSAGE_CLEAR_DIGITAL_TIMER == static_cast<int>(
+        CecMessageType::CLEAR_DIGITAL_TIMER),
+        "CecMessageType::CLEAR_DIGITAL_TIMER must match legacy value.");
+static_assert(CEC_MESSAGE_SET_AUDIO_RATE == static_cast<int>(CecMessageType::SET_AUDIO_RATE),
+        "CecMessageType::SET_AUDIO_RATE must match legacy value.");
+static_assert(CEC_MESSAGE_INACTIVE_SOURCE == static_cast<int>(CecMessageType::INACTIVE_SOURCE),
+        "CecMessageType::INACTIVE_SOURCE must match legacy value.");
+static_assert(CEC_MESSAGE_CEC_VERSION == static_cast<int>(CecMessageType::CEC_VERSION),
+        "CecMessageType::CEC_VERSION must match legacy value.");
+static_assert(CEC_MESSAGE_GET_CEC_VERSION == static_cast<int>(CecMessageType::GET_CEC_VERSION),
+        "CecMessageType::GET_CEC_VERSION must match legacy value.");
+static_assert(CEC_MESSAGE_VENDOR_COMMAND_WITH_ID == static_cast<int>(
+        CecMessageType::VENDOR_COMMAND_WITH_ID),
+        "CecMessageType::VENDOR_COMMAND_WITH_ID must match legacy value.");
+static_assert(CEC_MESSAGE_CLEAR_EXTERNAL_TIMER == static_cast<int>(
+        CecMessageType::CLEAR_EXTERNAL_TIMER),
+        "CecMessageType::CLEAR_EXTERNAL_TIMER must match legacy value.");
+static_assert(CEC_MESSAGE_SET_EXTERNAL_TIMER == static_cast<int>(
+        CecMessageType::SET_EXTERNAL_TIMER),
+        "CecMessageType::SET_EXTERNAL_TIMER must match legacy value.");
+static_assert(CEC_MESSAGE_INITIATE_ARC == static_cast<int>(CecMessageType::INITIATE_ARC),
+        "CecMessageType::INITIATE_ARC must match legacy value.");
+static_assert(CEC_MESSAGE_REPORT_ARC_INITIATED == static_cast<int>(
+        CecMessageType::REPORT_ARC_INITIATED),
+        "CecMessageType::REPORT_ARC_INITIATED must match legacy value.");
+static_assert(CEC_MESSAGE_REPORT_ARC_TERMINATED == static_cast<int>(
+        CecMessageType::REPORT_ARC_TERMINATED),
+        "CecMessageType::REPORT_ARC_TERMINATED must match legacy value.");
+static_assert(CEC_MESSAGE_REQUEST_ARC_INITIATION == static_cast<int>(
+        CecMessageType::REQUEST_ARC_INITIATION),
+        "CecMessageType::REQUEST_ARC_INITIATION must match legacy value.");
+static_assert(CEC_MESSAGE_REQUEST_ARC_TERMINATION == static_cast<int>(
+        CecMessageType::REQUEST_ARC_TERMINATION),
+        "CecMessageType::REQUEST_ARC_TERMINATION must match legacy value.");
+static_assert(CEC_MESSAGE_TERMINATE_ARC == static_cast<int>(CecMessageType::TERMINATE_ARC),
+        "CecMessageType::TERMINATE_ARC must match legacy value.");
+static_assert(CEC_MESSAGE_ABORT == static_cast<int>(CecMessageType::ABORT),
+        "CecMessageType::ABORT must match legacy value.");
+
+static_assert(ABORT_UNRECOGNIZED_MODE == static_cast<int>(AbortReason::UNRECOGNIZED_MODE),
+        "AbortReason::UNRECOGNIZED_MODE must match legacy value.");
+static_assert(ABORT_NOT_IN_CORRECT_MODE == static_cast<int>(AbortReason::NOT_IN_CORRECT_MODE),
+        "AbortReason::NOT_IN_CORRECT_MODE must match legacy value.");
+static_assert(ABORT_CANNOT_PROVIDE_SOURCE == static_cast<int>(AbortReason::CANNOT_PROVIDE_SOURCE),
+        "AbortReason::CANNOT_PROVIDE_SOURCE must match legacy value.");
+static_assert(ABORT_INVALID_OPERAND == static_cast<int>(AbortReason::INVALID_OPERAND),
+        "AbortReason::INVALID_OPERAND must match legacy value.");
+static_assert(ABORT_REFUSED == static_cast<int>(AbortReason::REFUSED),
+        "AbortReason::REFUSED must match legacy value.");
+static_assert(ABORT_UNABLE_TO_DETERMINE == static_cast<int>(AbortReason::UNABLE_TO_DETERMINE),
+        "AbortReason::UNABLE_TO_DETERMINE must match legacy value.");
+
+static_assert(HDMI_RESULT_SUCCESS == static_cast<int>(SendMessageResult::SUCCESS),
+        "SendMessageResult::SUCCESS must match legacy value.");
+static_assert(HDMI_RESULT_NACK == static_cast<int>(SendMessageResult::NACK),
+        "SendMessageResult::NACK must match legacy value.");
+static_assert(HDMI_RESULT_BUSY == static_cast<int>(SendMessageResult::BUSY),
+        "SendMessageResult::BUSY must match legacy value.");
+static_assert(HDMI_RESULT_FAIL == static_cast<int>(SendMessageResult::FAIL),
+        "SendMessageResult::FAIL must match legacy value.");
+
+static_assert(HDMI_INPUT == static_cast<int>(HdmiPortType::INPUT),
+        "HdmiPortType::INPUT must match legacy value.");
+static_assert(HDMI_OUTPUT == static_cast<int>(HdmiPortType::OUTPUT),
+        "HdmiPortType::OUTPUT must match legacy value.");
+
+static_assert(HDMI_OPTION_WAKEUP == static_cast<int>(OptionKey::WAKEUP),
+        "OptionKey::WAKEUP must match legacy value.");
+static_assert(HDMI_OPTION_ENABLE_CEC == static_cast<int>(OptionKey::ENABLE_CEC),
+        "OptionKey::ENABLE_CEC must match legacy value.");
+static_assert(HDMI_OPTION_SYSTEM_CEC_CONTROL == static_cast<int>(OptionKey::SYSTEM_CEC_CONTROL),
+        "OptionKey::SYSTEM_CEC_CONTROL must match legacy value.");
+
+sp<IHdmiCecCallback> HdmiCec::mCallback = nullptr;
+
+HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {
+}
+
+// Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+Return<Result> HdmiCec::addLogicalAddress(CecLogicalAddress addr) {
+    int ret = mDevice->add_logical_address(mDevice, static_cast<cec_logical_address_t>(addr));
+    switch (ret) {
+        case 0:
+            return Result::SUCCESS;
+        case -EINVAL:
+            return Result::FAILURE_INVALID_ARGS;
+        case -ENOTSUP:
+            return Result::FAILURE_NOT_SUPPORTED;
+        case -EBUSY:
+            return Result::FAILURE_BUSY;
+        default:
+            return Result::FAILURE_UNKNOWN;
+    }
+}
+
+Return<void> HdmiCec::clearLogicalAddress() {
+    mDevice->clear_logical_address(mDevice);
+    return Void();
+}
+
+Return<void> HdmiCec::getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) {
+    uint16_t addr;
+    int ret = mDevice->get_physical_address(mDevice, &addr);
+    switch (ret) {
+        case 0:
+            _hidl_cb(Result::SUCCESS, addr);
+            break;
+        case -EBADF:
+            _hidl_cb(Result::FAILURE_INVALID_STATE, addr);
+            break;
+        default:
+            _hidl_cb(Result::FAILURE_UNKNOWN, addr);
+            break;
+    }
+    return Void();
+}
+
+Return<SendMessageResult> HdmiCec::sendMessage(const CecMessage& message) {
+    cec_message_t legacyMessage {
+        .initiator = static_cast<cec_logical_address_t>(message.initiator),
+        .destination = static_cast<cec_logical_address_t>(message.destination),
+        .length = message.body.size(),
+    };
+    for (size_t i = 0; i < message.body.size(); ++i) {
+        legacyMessage.body[i] = static_cast<unsigned char>(message.body[i]);
+    }
+    return static_cast<SendMessageResult>(mDevice->send_message(mDevice, &legacyMessage));
+}
+
+Return<void> HdmiCec::setCallback(const sp<IHdmiCecCallback>& callback) {
+    mCallback = callback;
+    mDevice->register_event_callback(mDevice, eventCallback, nullptr);
+    return Void();
+}
+
+Return<int32_t> HdmiCec::getCecVersion() {
+    int version;
+    mDevice->get_version(mDevice, &version);
+    return static_cast<int32_t>(version);
+}
+
+Return<uint32_t> HdmiCec::getVendorId() {
+    uint32_t vendor_id;
+    mDevice->get_vendor_id(mDevice, &vendor_id);
+    return vendor_id;
+}
+
+Return<void> HdmiCec::getPortInfo(getPortInfo_cb _hidl_cb) {
+    struct hdmi_port_info* legacyPorts;
+    int numPorts;
+    hidl_vec<HdmiPortInfo> portInfos;
+    mDevice->get_port_info(mDevice, &legacyPorts, &numPorts);
+    portInfos.resize(numPorts);
+    for (int i = 0; i < numPorts; ++i) {
+        portInfos[i] = {
+            .type = static_cast<HdmiPortType>(legacyPorts[i].type),
+            .portId = static_cast<uint32_t>(legacyPorts[i].port_id),
+            .cecSupported = legacyPorts[i].cec_supported != 0,
+            .arcSupported = legacyPorts[i].arc_supported != 0,
+            .physicalAddress = legacyPorts[i].physical_address
+        };
+    }
+    _hidl_cb(portInfos);
+    return Void();
+}
+
+Return<void> HdmiCec::setOption(OptionKey key, bool value) {
+    mDevice->set_option(mDevice, static_cast<int>(key), value ? 1 : 0);
+    return Void();
+}
+
+Return<void> HdmiCec::setLanguage(const hidl_string& language) {
+    if (language.size() != 3) {
+        LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size()
+                << ".";
+        return Void();
+    }
+    const char *languageStr = language.c_str();
+    int convertedLanguage = ((languageStr[0] & 0xFF) << 16)
+            | ((languageStr[1] & 0xFF) << 8)
+            | (languageStr[2] & 0xFF);
+    mDevice->set_option(mDevice, HDMI_OPTION_SET_LANG, convertedLanguage);
+    return Void();
+}
+
+Return<void> HdmiCec::enableAudioReturnChannel(int32_t portId, bool enable) {
+    mDevice->set_audio_return_channel(mDevice, portId, enable ? 1 : 0);
+    return Void();
+}
+
+Return<bool> HdmiCec::isConnected(int32_t portId) {
+    return mDevice->is_connected(mDevice, portId) > 0;
+}
+
+
+IHdmiCec* HIDL_FETCH_IHdmiCec(const char* hal) {
+    hdmi_cec_device_t* hdmi_cec_device;
+    int ret = 0;
+    const hw_module_t* hw_module = nullptr;
+
+    ret = hw_get_module (HDMI_CEC_HARDWARE_MODULE_ID, &hw_module);
+    if (ret == 0) {
+        ret = hdmi_cec_open (hw_module, &hdmi_cec_device);
+        if (ret != 0) {
+            LOG(ERROR) << "hdmi_cec_open " << hal << " failed: " << ret;
+        }
+    } else {
+        LOG(ERROR) << "hw_get_module " << hal << " failed: " << ret;
+    }
+
+    if (ret == 0) {
+        return new HdmiCec(hdmi_cec_device);
+    } else {
+        LOG(ERROR) << "Passthrough failed to load legacy HAL.";
+        return nullptr;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/HdmiCec.h b/tv/cec/1.0/default/HdmiCec.h
new file mode 100644
index 0000000..34a3bb0
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCec.h
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
+#define ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
+
+#include <algorithm>
+
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <hidl/Status.h>
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::cec::V1_0::CecLogicalAddress;
+using ::android::hardware::tv::cec::V1_0::CecMessage;
+using ::android::hardware::tv::cec::V1_0::MaxLength;
+using ::android::hardware::tv::cec::V1_0::HdmiPortInfo;
+using ::android::hardware::tv::cec::V1_0::IHdmiCec;
+using ::android::hardware::tv::cec::V1_0::IHdmiCecCallback;
+using ::android::hardware::tv::cec::V1_0::OptionKey;
+using ::android::hardware::tv::cec::V1_0::Result;
+using ::android::hardware::tv::cec::V1_0::SendMessageResult;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct HdmiCec : public IHdmiCec {
+    HdmiCec(hdmi_cec_device_t* device);
+    // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+    Return<Result> addLogicalAddress(CecLogicalAddress addr)  override;
+    Return<void> clearLogicalAddress()  override;
+    Return<void> getPhysicalAddress(getPhysicalAddress_cb _hidl_cb)  override;
+    Return<SendMessageResult> sendMessage(const CecMessage& message)  override;
+    Return<void> setCallback(const sp<IHdmiCecCallback>& callback)  override;
+    Return<int32_t> getCecVersion()  override;
+    Return<uint32_t> getVendorId()  override;
+    Return<void> getPortInfo(getPortInfo_cb _hidl_cb)  override;
+    Return<void> setOption(OptionKey key, bool value)  override;
+    Return<void> setLanguage(const hidl_string& language)  override;
+    Return<void> enableAudioReturnChannel(int32_t portId, bool enable)  override;
+    Return<bool> isConnected(int32_t portId)  override;
+
+    static void eventCallback(const hdmi_event_t* event, void* /* arg */) {
+        if (mCallback != nullptr && event != nullptr) {
+            if (event->type == HDMI_EVENT_CEC_MESSAGE) {
+                size_t length = std::min(event->cec.length,
+                        static_cast<size_t>(MaxLength::MESSAGE_BODY));
+                CecMessage cecMessage {
+                    .initiator = static_cast<CecLogicalAddress>(event->cec.initiator),
+                    .destination = static_cast<CecLogicalAddress>(event->cec.destination),
+                };
+                cecMessage.body.resize(length);
+                for (size_t i = 0; i < length; ++i) {
+                    cecMessage.body[i] = static_cast<uint8_t>(event->cec.body[i]);
+                }
+                mCallback->onCecMessage(cecMessage);
+            } else if (event->type == HDMI_EVENT_HOT_PLUG) {
+                HotplugEvent hotplugEvent {
+                    .connected = event->hotplug.connected > 0,
+                    .portId = static_cast<uint32_t>(event->hotplug.port_id)
+                };
+                mCallback->onHotplugEvent(hotplugEvent);
+            }
+        }
+    }
+
+private:
+    static sp<IHdmiCecCallback> mCallback;
+    const hdmi_cec_device_t* mDevice;
+};
+
+extern "C" IHdmiCec* HIDL_FETCH_IHdmiCec(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
diff --git a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
new file mode 100644
index 0000000..1af32cb
--- /dev/null
+++ b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
@@ -0,0 +1,4 @@
+service cec-hal-1-0 /system/bin/hw/android.hardware.tv.cec@1.0-service
+    class hal
+    user system
+    group system
diff --git a/tv/cec/1.0/default/service.cpp b/tv/cec/1.0/default/service.cpp
new file mode 100644
index 0000000..3c11e24
--- /dev/null
+++ b/tv/cec/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.cec@1.0-service"
+
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::tv::cec::V1_0::IHdmiCec;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IHdmiCec>("tv.cec");
+}
diff --git a/tv/cec/1.0/types.hal b/tv/cec/1.0/types.hal
new file mode 100644
index 0000000..ec2e373
--- /dev/null
+++ b/tv/cec/1.0/types.hal
@@ -0,0 +1,222 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.cec@1.0;
+
+enum MaxLength : int32_t {
+    MESSAGE_BODY = 15,
+};
+
+enum CecDeviceType : int32_t {
+    INACTIVE = -1,
+    TV = 0,
+    RECORDER = 1,
+    TUNER = 3,
+    PLAYBACK = 4,
+    AUDIO_SYSTEM = 5,
+    MAX = AUDIO_SYSTEM,
+};
+
+enum CecLogicalAddress : int32_t {
+    TV = 0,
+    RECORDER_1 = 1,
+    RECORDER_2 = 2,
+    TUNER_1 = 3,
+    PLAYBACK_1 = 4,
+    AUDIO_SYSTEM = 5,
+    TUNER_2 = 6,
+    TUNER_3 = 7,
+    PLAYBACK_2 = 8,
+    RECORDER_3 = 9,
+    TUNER_4 = 10,
+    PLAYBACK_3 = 11,
+    FREE_USE = 14,
+    UNREGISTERED = 15, // as Initiator address
+    BROADCAST = 15, // as Destination address
+};
+
+/*
+ * HDMI CEC message types. The assigned values represent opcode used in CEC
+ * frame as specified in CEC Table 8-26 of the CEC Spec 1.4b.
+ */
+enum CecMessageType : int32_t {
+    FEATURE_ABORT = 0x00,
+    IMAGE_VIEW_ON = 0x04,
+    TUNER_STEP_INCREMENT = 0x05,
+    TUNER_STEP_DECREMENT = 0x06,
+    TUNER_DEVICE_STATUS = 0x07,
+    GIVE_TUNER_DEVICE_STATUS = 0x08,
+    RECORD_ON = 0x09,
+    RECORD_STATUS = 0x0A,
+    RECORD_OFF = 0x0B,
+    TEXT_VIEW_ON = 0x0D,
+    RECORD_TV_SCREEN = 0x0F,
+    GIVE_DECK_STATUS = 0x1A,
+    DECK_STATUS = 0x1B,
+    SET_MENU_LANGUAGE = 0x32,
+    CLEAR_ANALOG_TIMER = 0x33,
+    SET_ANALOG_TIMER = 0x34,
+    TIMER_STATUS = 0x35,
+    STANDBY = 0x36,
+    PLAY = 0x41,
+    DECK_CONTROL = 0x42,
+    TIMER_CLEARED_STATUS = 0x43,
+    USER_CONTROL_PRESSED = 0x44,
+    USER_CONTROL_RELEASED = 0x45,
+    GIVE_OSD_NAME = 0x46,
+    SET_OSD_NAME = 0x47,
+    SET_OSD_STRING = 0x64,
+    SET_TIMER_PROGRAM_TITLE = 0x67,
+    SYSTEM_AUDIO_MODE_REQUEST = 0x70,
+    GIVE_AUDIO_STATUS = 0x71,
+    SET_SYSTEM_AUDIO_MODE = 0x72,
+    REPORT_AUDIO_STATUS = 0x7A,
+    GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
+    SYSTEM_AUDIO_MODE_STATUS = 0x7E,
+    ROUTING_CHANGE = 0x80,
+    ROUTING_INFORMATION = 0x81,
+    ACTIVE_SOURCE = 0x82,
+    GIVE_PHYSICAL_ADDRESS = 0x83,
+    REPORT_PHYSICAL_ADDRESS = 0x84,
+    REQUEST_ACTIVE_SOURCE = 0x85,
+    SET_STREAM_PATH = 0x86,
+    DEVICE_VENDOR_ID = 0x87,
+    VENDOR_COMMAND = 0x89,
+    VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+    VENDOR_REMOTE_BUTTON_UP = 0x8B,
+    GIVE_DEVICE_VENDOR_ID = 0x8C,
+    MENU_REQUEST = 0x8D,
+    MENU_STATUS = 0x8E,
+    GIVE_DEVICE_POWER_STATUS = 0x8F,
+    REPORT_POWER_STATUS = 0x90,
+    GET_MENU_LANGUAGE = 0x91,
+    SELECT_ANALOG_SERVICE = 0x92,
+    SELECT_DIGITAL_SERVICE = 0x93,
+    SET_DIGITAL_TIMER = 0x97,
+    CLEAR_DIGITAL_TIMER = 0x99,
+    SET_AUDIO_RATE = 0x9A,
+    INACTIVE_SOURCE = 0x9D,
+    CEC_VERSION = 0x9E,
+    GET_CEC_VERSION = 0x9F,
+    VENDOR_COMMAND_WITH_ID = 0xA0,
+    CLEAR_EXTERNAL_TIMER = 0xA1,
+    SET_EXTERNAL_TIMER = 0xA2,
+    INITIATE_ARC = 0xC0,
+    REPORT_ARC_INITIATED = 0xC1,
+    REPORT_ARC_TERMINATED = 0xC2,
+    REQUEST_ARC_INITIATION = 0xC3,
+    REQUEST_ARC_TERMINATION = 0xC4,
+    TERMINATE_ARC = 0xC5,
+    ABORT = 0xFF,
+};
+
+/*
+ * Operand description [Abort Reason]
+ */
+enum AbortReason : int32_t {
+    UNRECOGNIZED_MODE = 0,
+    NOT_IN_CORRECT_MODE = 1,
+    CANNOT_PROVIDE_SOURCE = 2,
+    INVALID_OPERAND = 3,
+    REFUSED = 4,
+    UNABLE_TO_DETERMINE = 5,
+};
+
+enum Result : int32_t {
+    SUCCESS = 0,
+    FAILURE_UNKNOWN = 1,
+    FAILURE_INVALID_ARGS = 2,
+    FAILURE_INVALID_STATE = 3,
+    FAILURE_NOT_SUPPORTED = 4,
+    FAILURE_BUSY = 5,
+};
+
+/*
+ * error code used for send_message.
+ */
+enum SendMessageResult : int32_t {
+    SUCCESS = 0,
+    NACK = 1, // not acknowledged
+    BUSY = 2, // bus is busy
+    FAIL = 3,
+};
+
+/*
+ * HDMI port type.
+ */
+enum HdmiPortType : int32_t {
+    INPUT = 0,
+    OUTPUT = 1,
+};
+
+/*
+ * Options used for IHdmiCec.setOption()
+ */
+enum OptionKey : int32_t {
+    /* When set to false, HAL does not wake up the system upon receiving <Image
+     * View On> or <Text View On>. Used when user changes the TV settings to
+     * disable the auto TV on functionality.
+     * True by default.
+     */
+    WAKEUP = 1,
+
+    /* When set to false, all the CEC commands are discarded. Used when user
+     * changes the TV settings to disable CEC functionality.
+     * True by default.
+     */
+    ENABLE_CEC = 2,
+
+    /* Setting this flag to false means Android system must stop handling CEC
+     * service and yield the control over to the microprocessor that is powered
+     * on through the standby mode. When set to true, the system must gain the
+     * control over, hence telling the microprocessor to stop handling the CEC
+     * commands. For example, this may be called when system goes in and out of
+     * standby mode to notify the microprocessor that it should start/stop
+     * handling CEC commands on behalf of the system.
+     * False by default.
+     */
+    SYSTEM_CEC_CONTROL = 3,
+
+    /* Option 4 not used */
+};
+
+struct CecMessage {
+    /* logical address of sender */
+    CecLogicalAddress initiator;
+
+    /* logical address of receiver */
+    CecLogicalAddress destination;
+
+    /* The maximum size of body is 15 (MaxLength::MESSAGE_BODY) as specified in
+     * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored. */
+    vec<uint8_t> body;
+};
+
+struct HotplugEvent {
+    bool connected;
+    uint32_t portId;
+};
+
+/*
+ * HDMI port descriptor
+ */
+struct HdmiPortInfo {
+    HdmiPortType type;
+    uint32_t portId; // Should start from 1 which corresponds to HDMI "port 1".
+    bool cecSupported;
+    bool arcSupported;
+    uint16_t physicalAddress;
+};
diff --git a/tv/cec/1.0/vts/Android.mk b/tv/cec/1.0/vts/Android.mk
new file mode 100644
index 0000000..fc636f7
--- /dev/null
+++ b/tv/cec/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/tv_cec/hidl/Android.mk
diff --git a/tv/cec/1.0/vts/HdmiCec.vts b/tv/cec/1.0/vts/HdmiCec.vts
new file mode 100644
index 0000000..d7d09de
--- /dev/null
+++ b/tv/cec/1.0/vts/HdmiCec.vts
@@ -0,0 +1,172 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IHdmiCec"
+
+package: "android.hardware.tv.cec"
+
+import: "android.hardware.tv.cec@1.0::IHdmiCecCallback"
+import: "android.hardware.tv.cec@1.0::types"
+
+interface: {
+    api: {
+        name: "addLogicalAddress"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::cec::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::cec::V1_0::CecLogicalAddress"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "clearLogicalAddress"
+        callflow: {
+            next: "addLogicalAddress"
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "getPhysicalAddress"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::cec::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint16_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "sendMessage"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::cec::V1_0::SendMessageResult"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::tv::cec::V1_0::CecMessage"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "setCallback"
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "IHdmiCecCallback"
+            is_callback: true
+        }
+        callflow: {
+            next: "addLogicalAddress"
+        }
+        callflow: {
+            entry: true
+        }
+    }
+
+    api: {
+        name: "getCecVersion"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getVendorId"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "getPortInfo"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::tv::cec::V1_0::HdmiPortInfo"
+            }
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "setOption"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::cec::V1_0::OptionKey"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "setLanguage"
+        arg: {
+            type: TYPE_STRING
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "enableAudioReturnChannel"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+    api: {
+        name: "isConnected"
+        return_type_hidl: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        callflow: {
+            next: "*"
+        }
+    }
+
+}
diff --git a/tv/cec/1.0/vts/HdmiCecCallback.vts b/tv/cec/1.0/vts/HdmiCecCallback.vts
new file mode 100644
index 0000000..864e6f5
--- /dev/null
+++ b/tv/cec/1.0/vts/HdmiCecCallback.vts
@@ -0,0 +1,26 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IHdmiCecCallback"
+
+package: "android.hardware.tv.cec"
+
+import: "android.hardware.tv.cec@1.0::types"
+
+interface: {
+    api: {
+        name: "onCecMessage"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::tv::cec::V1_0::CecMessage"
+        }
+    }
+
+    api: {
+        name: "onHotplugEvent"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::tv::cec::V1_0::HotplugEvent"
+        }
+    }
+
+}
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/__init__.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/__init__.py
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/Android.mk b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/__init__.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/__init__.py
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/Android.mk b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/Android.mk
new file mode 100644
index 0000000..ece38d7
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := TvCecHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/tv_cec/hidl/host
+include test/vts/tools/build/Android.host_config.mk
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/AndroidTest.xml b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..79584d5
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Tv Input HIDL HAL's host-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/HdmiCec.vts->/data/local/tmp/spec/HdmiCec.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/HdmiCecCallback.vts->/data/local/tmp/spec/HdmiCecCallback.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+        <option name="cleanup" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="TvCecHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py
new file mode 100644
index 0000000..5f7aaf1
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import logging
+
+from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+
+
+class TvCecHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """Host testcase class for the TV HDMI_CEC HIDL HAL."""
+
+    def setUpClass(self):
+        """Creates a mirror and init tv hdmi cec hal service."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        self.dut.shell.one.Execute(
+            "setprop vts.hal.vts.hidl.get_stub true")
+
+        self.dut.hal.InitHidlHal(
+            target_type="tv_cec",
+            target_basepaths=self.dut.libPaths,
+            target_version=1.0,
+            target_package="android.hardware.tv.cec",
+            target_component_name="IHdmiCec",
+            hw_binder_service_name="cec-hal-1-0",
+            bits=64 if self.dut.is64Bit else 32)
+
+    def testGetCecVersion1(self):
+        """A simple test case which queries the cec version."""
+        logging.info('DIR HAL %s', dir(self.dut.hal))
+        version = self.dut.hal.tv_cec.getCecVersion()
+        logging.info('Cec version: %s', version)
+
+    def testSendRandomMessage(self):
+        """A test case which sends a random message."""
+        self.vtypes = self.dut.hal.tv_cec.GetHidlTypeInterface("types")
+        logging.info("tv_cec types: %s", self.vtypes)
+
+        cec_message = {
+            "initiator": self.vtypes.TV,
+            "destination": self.vtypes.PLAYBACK_1,
+            "body": [1, 2, 3]
+        }
+        message = self.vtypes.Py2Pb("CecMessage", cec_message)
+        logging.info("message: %s", message)
+        result = self.dut.hal.tv_cec.sendMessage(message)
+        logging.info('sendMessage result: %s', result)
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/__init__.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host/__init__.py
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/Android.mk b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/Android.mk
new file mode 100644
index 0000000..40536a5
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := TvCecHidlProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/tv_cec/hidl/host_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/AndroidTest.xml b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/AndroidTest.xml
new file mode 100644
index 0000000..ffd857e
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<configuration description="Config for VTS Tv Input HIDL HAL's host-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/HdmiCec.vts->/data/local/tmp/spec/HdmiCec.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/HdmiCecCallback.vts->/data/local/tmp/spec/HdmiCecCallback.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/cec/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+        <option name="cleanup" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="TvCecHidlProfilingTest" />
+        <option name="test-case-path" value="vts/testcases/hal/tv_cec/hidl/host/TvCecHidlTest" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/__init__.py b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/cec/1.0/vts/functional/vts/testcases/hal/tv_cec/hidl/host_profiling/__init__.py
diff --git a/tv/cec/1.0/vts/types.vts b/tv/cec/1.0/vts/types.vts
new file mode 100644
index 0000000..ae972a5
--- /dev/null
+++ b/tv/cec/1.0/vts/types.vts
@@ -0,0 +1,604 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.tv.cec"
+
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::MaxLength"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "MESSAGE_BODY"
+        scalar_value: {
+            int32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::CecDeviceType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INACTIVE"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "TV"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RECORDER"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TUNER"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "PLAYBACK"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "AUDIO_SYSTEM"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::CecLogicalAddress"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "TV"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RECORDER_1"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "RECORDER_2"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "TUNER_1"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "PLAYBACK_1"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "AUDIO_SYSTEM"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "TUNER_2"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "TUNER_3"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "PLAYBACK_2"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "RECORDER_3"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "TUNER_4"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "PLAYBACK_3"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "FREE_USE"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "UNREGISTERED"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "BROADCAST"
+        scalar_value: {
+            int32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::CecMessageType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FEATURE_ABORT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "IMAGE_VIEW_ON"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "TUNER_STEP_INCREMENT"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "TUNER_STEP_DECREMENT"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "TUNER_DEVICE_STATUS"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "GIVE_TUNER_DEVICE_STATUS"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "RECORD_ON"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "RECORD_STATUS"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "RECORD_OFF"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "TEXT_VIEW_ON"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "RECORD_TV_SCREEN"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "GIVE_DECK_STATUS"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "DECK_STATUS"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "SET_MENU_LANGUAGE"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "CLEAR_ANALOG_TIMER"
+        scalar_value: {
+            int32_t: 51
+        }
+        enumerator: "SET_ANALOG_TIMER"
+        scalar_value: {
+            int32_t: 52
+        }
+        enumerator: "TIMER_STATUS"
+        scalar_value: {
+            int32_t: 53
+        }
+        enumerator: "STANDBY"
+        scalar_value: {
+            int32_t: 54
+        }
+        enumerator: "PLAY"
+        scalar_value: {
+            int32_t: 65
+        }
+        enumerator: "DECK_CONTROL"
+        scalar_value: {
+            int32_t: 66
+        }
+        enumerator: "TIMER_CLEARED_STATUS"
+        scalar_value: {
+            int32_t: 67
+        }
+        enumerator: "USER_CONTROL_PRESSED"
+        scalar_value: {
+            int32_t: 68
+        }
+        enumerator: "USER_CONTROL_RELEASED"
+        scalar_value: {
+            int32_t: 69
+        }
+        enumerator: "GIVE_OSD_NAME"
+        scalar_value: {
+            int32_t: 70
+        }
+        enumerator: "SET_OSD_NAME"
+        scalar_value: {
+            int32_t: 71
+        }
+        enumerator: "SET_OSD_STRING"
+        scalar_value: {
+            int32_t: 100
+        }
+        enumerator: "SET_TIMER_PROGRAM_TITLE"
+        scalar_value: {
+            int32_t: 103
+        }
+        enumerator: "SYSTEM_AUDIO_MODE_REQUEST"
+        scalar_value: {
+            int32_t: 112
+        }
+        enumerator: "GIVE_AUDIO_STATUS"
+        scalar_value: {
+            int32_t: 113
+        }
+        enumerator: "SET_SYSTEM_AUDIO_MODE"
+        scalar_value: {
+            int32_t: 114
+        }
+        enumerator: "REPORT_AUDIO_STATUS"
+        scalar_value: {
+            int32_t: 122
+        }
+        enumerator: "GIVE_SYSTEM_AUDIO_MODE_STATUS"
+        scalar_value: {
+            int32_t: 125
+        }
+        enumerator: "SYSTEM_AUDIO_MODE_STATUS"
+        scalar_value: {
+            int32_t: 126
+        }
+        enumerator: "ROUTING_CHANGE"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "ROUTING_INFORMATION"
+        scalar_value: {
+            int32_t: 129
+        }
+        enumerator: "ACTIVE_SOURCE"
+        scalar_value: {
+            int32_t: 130
+        }
+        enumerator: "GIVE_PHYSICAL_ADDRESS"
+        scalar_value: {
+            int32_t: 131
+        }
+        enumerator: "REPORT_PHYSICAL_ADDRESS"
+        scalar_value: {
+            int32_t: 132
+        }
+        enumerator: "REQUEST_ACTIVE_SOURCE"
+        scalar_value: {
+            int32_t: 133
+        }
+        enumerator: "SET_STREAM_PATH"
+        scalar_value: {
+            int32_t: 134
+        }
+        enumerator: "DEVICE_VENDOR_ID"
+        scalar_value: {
+            int32_t: 135
+        }
+        enumerator: "VENDOR_COMMAND"
+        scalar_value: {
+            int32_t: 137
+        }
+        enumerator: "VENDOR_REMOTE_BUTTON_DOWN"
+        scalar_value: {
+            int32_t: 138
+        }
+        enumerator: "VENDOR_REMOTE_BUTTON_UP"
+        scalar_value: {
+            int32_t: 139
+        }
+        enumerator: "GIVE_DEVICE_VENDOR_ID"
+        scalar_value: {
+            int32_t: 140
+        }
+        enumerator: "MENU_REQUEST"
+        scalar_value: {
+            int32_t: 141
+        }
+        enumerator: "MENU_STATUS"
+        scalar_value: {
+            int32_t: 142
+        }
+        enumerator: "GIVE_DEVICE_POWER_STATUS"
+        scalar_value: {
+            int32_t: 143
+        }
+        enumerator: "REPORT_POWER_STATUS"
+        scalar_value: {
+            int32_t: 144
+        }
+        enumerator: "GET_MENU_LANGUAGE"
+        scalar_value: {
+            int32_t: 145
+        }
+        enumerator: "SELECT_ANALOG_SERVICE"
+        scalar_value: {
+            int32_t: 146
+        }
+        enumerator: "SELECT_DIGITAL_SERVICE"
+        scalar_value: {
+            int32_t: 147
+        }
+        enumerator: "SET_DIGITAL_TIMER"
+        scalar_value: {
+            int32_t: 151
+        }
+        enumerator: "CLEAR_DIGITAL_TIMER"
+        scalar_value: {
+            int32_t: 153
+        }
+        enumerator: "SET_AUDIO_RATE"
+        scalar_value: {
+            int32_t: 154
+        }
+        enumerator: "INACTIVE_SOURCE"
+        scalar_value: {
+            int32_t: 157
+        }
+        enumerator: "CEC_VERSION"
+        scalar_value: {
+            int32_t: 158
+        }
+        enumerator: "GET_CEC_VERSION"
+        scalar_value: {
+            int32_t: 159
+        }
+        enumerator: "VENDOR_COMMAND_WITH_ID"
+        scalar_value: {
+            int32_t: 160
+        }
+        enumerator: "CLEAR_EXTERNAL_TIMER"
+        scalar_value: {
+            int32_t: 161
+        }
+        enumerator: "SET_EXTERNAL_TIMER"
+        scalar_value: {
+            int32_t: 162
+        }
+        enumerator: "INITIATE_ARC"
+        scalar_value: {
+            int32_t: 192
+        }
+        enumerator: "REPORT_ARC_INITIATED"
+        scalar_value: {
+            int32_t: 193
+        }
+        enumerator: "REPORT_ARC_TERMINATED"
+        scalar_value: {
+            int32_t: 194
+        }
+        enumerator: "REQUEST_ARC_INITIATION"
+        scalar_value: {
+            int32_t: 195
+        }
+        enumerator: "REQUEST_ARC_TERMINATION"
+        scalar_value: {
+            int32_t: 196
+        }
+        enumerator: "TERMINATE_ARC"
+        scalar_value: {
+            int32_t: 197
+        }
+        enumerator: "ABORT"
+        scalar_value: {
+            int32_t: 255
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::AbortReason"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNRECOGNIZED_MODE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NOT_IN_CORRECT_MODE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CANNOT_PROVIDE_SOURCE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "INVALID_OPERAND"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "REFUSED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "UNABLE_TO_DETERMINE"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::Result"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FAILURE_UNKNOWN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "FAILURE_INVALID_ARGS"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FAILURE_INVALID_STATE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "FAILURE_NOT_SUPPORTED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "FAILURE_BUSY"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::SendMessageResult"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SUCCESS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NACK"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "BUSY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FAIL"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::HdmiPortType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INPUT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "OUTPUT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::OptionKey"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "WAKEUP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ENABLE_CEC"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SYSTEM_CEC_CONTROL"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::CecMessage"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "initiator"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::tv::cec::V1_0::CecLogicalAddress"
+    }
+    struct_value: {
+        name: "destination"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::tv::cec::V1_0::CecLogicalAddress"
+    }
+    struct_value: {
+        name: "body"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::HotplugEvent"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "connected"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "portId"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::cec::V1_0::HdmiPortInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::tv::cec::V1_0::HdmiPortType"
+    }
+    struct_value: {
+        name: "portId"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "cecSupported"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "arcSupported"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "physicalAddress"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+}
+
diff --git a/tv/cec/Android.mk b/tv/cec/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tv/cec/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tv/input/1.0/Android.bp b/tv/input/1.0/Android.bp
new file mode 100644
index 0000000..6bcb985
--- /dev/null
+++ b/tv/input/1.0/Android.bp
@@ -0,0 +1,222 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.tv.input@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0",
+    srcs: [
+        "types.hal",
+        "ITvInput.hal",
+        "ITvInputCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/types.cpp",
+        "android/hardware/tv/input/1.0/TvInputAll.cpp",
+        "android/hardware/tv/input/1.0/TvInputCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0",
+    srcs: [
+        "types.hal",
+        "ITvInput.hal",
+        "ITvInputCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/types.h",
+        "android/hardware/tv/input/1.0/ITvInput.h",
+        "android/hardware/tv/input/1.0/IHwTvInput.h",
+        "android/hardware/tv/input/1.0/BnHwTvInput.h",
+        "android/hardware/tv/input/1.0/BpHwTvInput.h",
+        "android/hardware/tv/input/1.0/BsTvInput.h",
+        "android/hardware/tv/input/1.0/ITvInputCallback.h",
+        "android/hardware/tv/input/1.0/IHwTvInputCallback.h",
+        "android/hardware/tv/input/1.0/BnHwTvInputCallback.h",
+        "android/hardware/tv/input/1.0/BpHwTvInputCallback.h",
+        "android/hardware/tv/input/1.0/BsTvInputCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.input@1.0",
+    generated_sources: ["android.hardware.tv.input@1.0_genc++"],
+    generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "types.hal",
+        "ITvInput.hal",
+        "ITvInputCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/types.vts.cpp",
+        "android/hardware/tv/input/1.0/TvInput.vts.cpp",
+        "android/hardware/tv/input/1.0/TvInputCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "types.hal",
+        "ITvInput.hal",
+        "ITvInputCallback.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/types.vts.h",
+        "android/hardware/tv/input/1.0/TvInput.vts.h",
+        "android/hardware/tv/input/1.0/TvInputCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.input.vts.driver@1.0",
+    generated_sources: ["android.hardware.tv.input.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.tv.input.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.input.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.input@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input@1.0-ITvInput-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "ITvInput.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/TvInput.vts.cpp",
+        "android/hardware/tv/input/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input@1.0-ITvInput-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "ITvInput.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/TvInput.vts.h",
+        "android/hardware/tv/input/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.input@1.0-ITvInput-vts.profiler",
+    generated_sources: ["android.hardware.tv.input@1.0-ITvInput-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.tv.input@1.0-ITvInput-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.input@1.0-ITvInput-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.input@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "ITvInputCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/TvInputCallback.vts.cpp",
+        "android/hardware/tv/input/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tv.input@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/tv/input/1.0/ $(genDir)/android/hardware/tv/input/1.0/",
+    srcs: [
+        "ITvInputCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/tv/input/1.0/TvInputCallback.vts.h",
+        "android/hardware/tv/input/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler",
+    generated_sources: ["android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.tv.input@1.0-ITvInputCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hardware.audio.common@2.0",
+        "android.hidl.base@1.0",
+        "android.hardware.tv.input@1.0",
+    ],
+}
diff --git a/tv/input/1.0/Android.mk b/tv/input/1.0/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tv/input/1.0/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tv/input/1.0/ITvInput.hal b/tv/input/1.0/ITvInput.hal
new file mode 100644
index 0000000..43de276
--- /dev/null
+++ b/tv/input/1.0/ITvInput.hal
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.input@1.0;
+
+import ITvInputCallback;
+
+interface ITvInput {
+    /*
+     * Sets a callback for events.
+     *
+     * Note that initially no device is available in the client side, so the
+     * implementation must notify all the currently available devices including
+     * static devices via callback once callback is set.
+     *
+     * @param callback Callback object to pass events.
+     */
+    @entry
+    @exit
+    @callflow(next={"getStreamConfigurations"})
+    setCallback(ITvInputCallback callback);
+
+    /*
+     * Gets stream configurations for a specific device.
+     *
+     * The configs object is valid only until the next
+     * STREAM_CONFIGURATIONS_CHANGED event.
+     *
+     * @param deviceId Device ID for the configurations.
+     * @return result OK upon success. Otherwise,
+     *         INVALID_ARGUMENTS if the given device ID is not valid.
+     * @return configurations An array of available configurations.
+     */
+    @callflow(next={"openStream", "getStreamConfigurations", "closeStream"})
+    getStreamConfigurations(int32_t deviceId)
+            generates (Result result, vec<TvStreamConfig> configurations);
+
+    /*
+     * Opens a specific stream in a device.
+     *
+     * @param deviceId Device ID for the steam to open.
+     * @param streamId Steam ID for the steam to open. Must be one of the
+     *         stream IDs returned from getStreamConfigurations().
+     * @return result OK upon success. Otherwise,
+     *         INVALID_ARGUMENTS if any of given IDs are not valid;
+     *         INVALID_STATE if the stream with the given ID is already open;
+     *         NO_RESOURCE if the client must close other streams to open the
+     *                 stream.
+     * @return sidebandStream handle for sideband stream.
+     */
+    @callflow(next={"closeStream", "getStreamConfigurations", "openStream"})
+    openStream(int32_t deviceId, int32_t streamId)
+            generates (Result result, handle sidebandStream);
+
+    /*
+     * Closes a specific stream in a device.
+     *
+     * @param deviceId Device ID for the steam to open.
+     * @param streamId Steam ID for the steam to open.
+     * @return result OK upon success. Otherwise,
+     *         INVALID_ARGUMENTS if any of given IDs are not valid;
+     *         INVALID_STATE if the stream with the given ID is not open.
+     */
+    @callflow(next={"getStreamConfigurations", "openStream", "closeStream"})
+    closeStream(int32_t deviceId, int32_t streamId) generates (Result result);
+};
diff --git a/tv/input/1.0/ITvInputCallback.hal b/tv/input/1.0/ITvInputCallback.hal
new file mode 100644
index 0000000..f2f07a0
--- /dev/null
+++ b/tv/input/1.0/ITvInputCallback.hal
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.input@1.0;
+
+interface ITvInputCallback {
+    /*
+     * Notifies the client that an event has occured. For possible event types,
+     * check TvInputEventType.
+     *
+     * @param event Event passed to the client.
+     */
+    notify(TvInputEvent event);
+};
diff --git a/tv/input/1.0/default/Android.mk b/tv/input/1.0/default/Android.mk
new file mode 100644
index 0000000..9728015
--- /dev/null
+++ b/tv/input/1.0/default/Android.mk
@@ -0,0 +1,46 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tv.input@1.0-impl
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+    TvInput.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    liblog \
+    libhardware \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    libutils \
+    android.hardware.audio.common@2.0 \
+    android.hardware.tv.input@1.0 \
+
+include $(BUILD_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.tv.input@1.0-service
+LOCAL_INIT_RC := android.hardware.tv.input@1.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    liblog \
+    libcutils \
+    libdl \
+    libbase \
+    libutils \
+    libhardware_legacy \
+    libhardware \
+
+LOCAL_SHARED_LIBRARIES += \
+    libhwbinder \
+    libhidlbase \
+    libhidltransport \
+    android.hardware.audio.common@2.0 \
+    android.hardware.tv.input@1.0 \
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/tv/input/1.0/default/TvInput.cpp b/tv/input/1.0/default/TvInput.cpp
new file mode 100644
index 0000000..4cd1d40
--- /dev/null
+++ b/tv/input/1.0/default/TvInput.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.input@1.0-service"
+#include <android-base/logging.h>
+
+#include "TvInput.h"
+
+const native_handle_t kNullNativeHandle{sizeof(native_handle_t), 0, 0, {}};
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace input {
+namespace V1_0 {
+namespace implementation {
+
+static_assert(TV_INPUT_TYPE_OTHER_HARDWARE == static_cast<int>(TvInputType::OTHER),
+        "TvInputType::OTHER must match legacy value.");
+static_assert(TV_INPUT_TYPE_TUNER == static_cast<int>(TvInputType::TUNER),
+        "TvInputType::TUNER must match legacy value.");
+static_assert(TV_INPUT_TYPE_COMPOSITE == static_cast<int>(TvInputType::COMPOSITE),
+        "TvInputType::COMPOSITE must match legacy value.");
+static_assert(TV_INPUT_TYPE_SVIDEO == static_cast<int>(TvInputType::SVIDEO),
+        "TvInputType::SVIDEO must match legacy value.");
+static_assert(TV_INPUT_TYPE_SCART == static_cast<int>(TvInputType::SCART),
+        "TvInputType::SCART must match legacy value.");
+static_assert(TV_INPUT_TYPE_COMPONENT == static_cast<int>(TvInputType::COMPONENT),
+        "TvInputType::COMPONENT must match legacy value.");
+static_assert(TV_INPUT_TYPE_VGA == static_cast<int>(TvInputType::VGA),
+        "TvInputType::VGA must match legacy value.");
+static_assert(TV_INPUT_TYPE_DVI == static_cast<int>(TvInputType::DVI),
+        "TvInputType::DVI must match legacy value.");
+static_assert(TV_INPUT_TYPE_HDMI == static_cast<int>(TvInputType::HDMI),
+        "TvInputType::HDMI must match legacy value.");
+static_assert(TV_INPUT_TYPE_DISPLAY_PORT == static_cast<int>(TvInputType::DISPLAY_PORT),
+        "TvInputType::DISPLAY_PORT must match legacy value.");
+
+static_assert(TV_INPUT_EVENT_DEVICE_AVAILABLE == static_cast<int>(
+        TvInputEventType::DEVICE_AVAILABLE),
+        "TvInputEventType::DEVICE_AVAILABLE must match legacy value.");
+static_assert(TV_INPUT_EVENT_DEVICE_UNAVAILABLE == static_cast<int>(
+        TvInputEventType::DEVICE_UNAVAILABLE),
+        "TvInputEventType::DEVICE_UNAVAILABLE must match legacy value.");
+static_assert(TV_INPUT_EVENT_STREAM_CONFIGURATIONS_CHANGED == static_cast<int>(
+        TvInputEventType::STREAM_CONFIGURATIONS_CHANGED),
+        "TvInputEventType::STREAM_CONFIGURATIONS_CHANGED must match legacy value.");
+
+sp<ITvInputCallback> TvInput::mCallback = nullptr;
+
+TvInput::TvInput(tv_input_device_t* device) : mDevice(device) {
+    mCallbackOps.notify = &TvInput::notify;
+}
+
+TvInput::~TvInput() {
+    if (mDevice != nullptr) {
+        free(mDevice);
+    }
+}
+
+// Methods from ::android::hardware::tv_input::V1_0::ITvInput follow.
+Return<void> TvInput::setCallback(const sp<ITvInputCallback>& callback)  {
+    mCallback = callback;
+    if (mCallback != nullptr) {
+        mDevice->initialize(mDevice, &mCallbackOps, nullptr);
+    }
+    return Void();
+}
+
+Return<void> TvInput::getStreamConfigurations(int32_t deviceId, getStreamConfigurations_cb cb)  {
+    int32_t configCount = 0;
+    const tv_stream_config_t* configs = nullptr;
+    int ret = mDevice->get_stream_configurations(mDevice, deviceId, &configCount, &configs);
+    Result res = Result::UNKNOWN;
+    hidl_vec<TvStreamConfig> tvStreamConfigs;
+    if (ret == 0) {
+        res = Result::OK;
+        tvStreamConfigs.resize(getSupportedConfigCount(configCount, configs));
+        int32_t pos = 0;
+        for (int32_t i = 0; i < configCount; ++i) {
+            if (isSupportedStreamType(configs[i].type)) {
+                tvStreamConfigs[pos].streamId = configs[i].stream_id;
+                tvStreamConfigs[pos].maxVideoWidth = configs[i].max_video_width;
+                tvStreamConfigs[pos].maxVideoHeight = configs[i].max_video_height;
+                ++pos;
+            }
+        }
+    }
+    cb(res, tvStreamConfigs);
+    return Void();
+}
+
+Return<void> TvInput::openStream(int32_t deviceId, int32_t streamId, openStream_cb cb)  {
+    tv_stream_t stream;
+    stream.stream_id = streamId;
+    int ret = mDevice->open_stream(mDevice, deviceId, &stream);
+    Result res = Result::UNKNOWN;
+    native_handle_t* sidebandStream = nullptr;
+    if (ret == 0) {
+        if (isSupportedStreamType(stream.type)) {
+            res = Result::OK;
+            sidebandStream = stream.sideband_stream_source_handle;
+        }
+    } else {
+        // TODO(b/30814137)
+        sidebandStream = const_cast<native_handle_t*>(&kNullNativeHandle);
+        if (ret == -EBUSY) {
+            res = Result::NO_RESOURCE;
+        } else if (ret == -EEXIST) {
+            res = Result::INVALID_STATE;
+        } else if (ret == -EINVAL) {
+            res = Result::INVALID_ARGUMENTS;
+        }
+    }
+    cb(res, sidebandStream);
+    return Void();
+}
+
+Return<Result> TvInput::closeStream(int32_t deviceId, int32_t streamId)  {
+    int ret = mDevice->close_stream(mDevice, deviceId, streamId);
+    Result res = Result::UNKNOWN;
+    if (ret == 0) {
+        res = Result::OK;
+    } else if (ret == -ENOENT) {
+        res = Result::INVALID_STATE;
+    } else if (ret == -EINVAL) {
+        res = Result::INVALID_ARGUMENTS;
+    }
+    return res;
+}
+
+// static
+void TvInput::notify(struct tv_input_device* __unused, tv_input_event_t* event,
+        void* __unused) {
+    if (mCallback != nullptr && event != nullptr) {
+        // Capturing is no longer supported.
+        if (event->type >= TV_INPUT_EVENT_CAPTURE_SUCCEEDED) {
+            return;
+        }
+        TvInputEvent tvInputEvent;
+        tvInputEvent.type = static_cast<TvInputEventType>(event->type);
+        tvInputEvent.deviceInfo.deviceId = event->device_info.device_id;
+        tvInputEvent.deviceInfo.type = static_cast<TvInputType>(
+                event->device_info.type);
+        tvInputEvent.deviceInfo.portId = event->device_info.hdmi.port_id;
+        // TODO: Ensure the legacy audio type code is the same once audio HAL default
+        // implementation is ready.
+        tvInputEvent.deviceInfo.audioType = static_cast<AudioDevice>(
+                event->device_info.audio_type);
+        memset(tvInputEvent.deviceInfo.audioAddress.data(), 0,
+                tvInputEvent.deviceInfo.audioAddress.size());
+        const char* address = event->device_info.audio_address;
+        if (address != nullptr) {
+            size_t size = strlen(address);
+            if (size > tvInputEvent.deviceInfo.audioAddress.size()) {
+                LOG(ERROR) << "Audio address is too long. Address:" << address << "";
+                return;
+            }
+            for (size_t i = 0; i < size; ++i) {
+                tvInputEvent.deviceInfo.audioAddress[i] =
+                    static_cast<uint8_t>(event->device_info.audio_address[i]);
+            }
+        }
+        mCallback->notify(tvInputEvent);
+    }
+}
+
+// static
+uint32_t TvInput::getSupportedConfigCount(uint32_t configCount,
+        const tv_stream_config_t* configs) {
+    uint32_t supportedConfigCount = 0;
+    for (uint32_t i = 0; i < configCount; ++i) {
+        if (isSupportedStreamType(configs[i].type)) {
+            supportedConfigCount++;
+        }
+    }
+    return supportedConfigCount;
+}
+
+// static
+bool TvInput::isSupportedStreamType(int type) {
+    // Buffer producer type is no longer supported.
+    return type != TV_STREAM_TYPE_BUFFER_PRODUCER;
+}
+
+ITvInput* HIDL_FETCH_ITvInput(const char* /* name */) {
+    int ret = 0;
+    const hw_module_t* hw_module = nullptr;
+    tv_input_device_t* input_device;
+    ret = hw_get_module(TV_INPUT_HARDWARE_MODULE_ID, &hw_module);
+    if (ret == 0 && hw_module->methods->open != nullptr) {
+        ret = hw_module->methods->open(hw_module, TV_INPUT_DEFAULT_DEVICE,
+                reinterpret_cast<hw_device_t**>(&input_device));
+        if (ret == 0) {
+            return new TvInput(input_device);
+        }
+        else {
+            LOG(ERROR) << "Passthrough failed to load legacy HAL.";
+            return nullptr;
+        }
+    }
+    else {
+        LOG(ERROR) << "hw_get_module " << TV_INPUT_HARDWARE_MODULE_ID
+                   << " failed: " << ret;
+        return nullptr;
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace input
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/input/1.0/default/TvInput.h b/tv/input/1.0/default/TvInput.h
new file mode 100644
index 0000000..beb69f5
--- /dev/null
+++ b/tv/input/1.0/default/TvInput.h
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_TV_INPUT_V1_0_TVINPUT_H
+#define ANDROID_HARDWARE_TV_INPUT_V1_0_TVINPUT_H
+
+#include <android/hardware/tv/input/1.0/ITvInput.h>
+#include <hidl/Status.h>
+#include <hardware/tv_input.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace input {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::audio::common::V2_0::AudioDevice;
+using ::android::hardware::tv::input::V1_0::ITvInput;
+using ::android::hardware::tv::input::V1_0::ITvInputCallback;
+using ::android::hardware::tv::input::V1_0::Result;
+using ::android::hardware::tv::input::V1_0::TvInputEvent;
+using ::android::hardware::tv::input::V1_0::TvStreamConfig;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct TvInput : public ITvInput {
+    TvInput(tv_input_device_t* device);
+    ~TvInput();
+    Return<void> setCallback(const sp<ITvInputCallback>& callback)  override;
+    Return<void> getStreamConfigurations(int32_t deviceId,
+            getStreamConfigurations_cb _hidl_cb)  override;
+    Return<void> openStream(int32_t deviceId, int32_t streamId,
+            openStream_cb _hidl_cb)  override;
+    Return<Result> closeStream(int32_t deviceId, int32_t streamId)  override;
+
+    static void notify(struct tv_input_device* __unused, tv_input_event_t* event,
+            void* __unused);
+    static uint32_t getSupportedConfigCount(uint32_t configCount,
+            const tv_stream_config_t* configs);
+    static bool isSupportedStreamType(int type);
+
+    private:
+    static sp<ITvInputCallback> mCallback;
+    tv_input_callback_ops_t mCallbackOps;
+    tv_input_device_t* mDevice;
+};
+
+extern "C" ITvInput* HIDL_FETCH_ITvInput(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace input
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_INPUT_V1_0_TVINPUT_H
diff --git a/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
new file mode 100644
index 0000000..c5bc0b7
--- /dev/null
+++ b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
@@ -0,0 +1,4 @@
+service tv-input-1-0 /system/bin/hw/android.hardware.tv.input@1.0-service
+    class hal
+    user system
+    group system readproc
diff --git a/tv/input/1.0/default/service.cpp b/tv/input/1.0/default/service.cpp
new file mode 100644
index 0000000..d904d0b
--- /dev/null
+++ b/tv/input/1.0/default/service.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv_input@1.0-service"
+
+#include <android/hardware/tv/input/1.0/ITvInput.h>
+
+#include <hidl/LegacySupport.h>
+
+using android::sp;
+
+// Generated HIDL files
+using android::hardware::tv::input::V1_0::ITvInput;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<ITvInput>();
+}
diff --git a/tv/input/1.0/types.hal b/tv/input/1.0/types.hal
new file mode 100644
index 0000000..6852c70
--- /dev/null
+++ b/tv/input/1.0/types.hal
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tv.input@1.0;
+
+import android.hardware.audio.common@2.0;
+
+enum Result : int32_t {
+    OK,
+    UNKNOWN,
+    NO_RESOURCE,
+    INVALID_ARGUMENTS,
+    INVALID_STATE,
+};
+
+/* Type of physical TV input. */
+enum TvInputType : int32_t {
+    OTHER = 1,         // Generic hardware.
+    TUNER = 2,         // Tuner. e.g. built-in terrestrial tuner
+    COMPOSITE = 3,
+    SVIDEO = 4,
+    SCART = 5,
+    COMPONENT = 6,
+    VGA = 7,
+    DVI = 8,
+    HDMI = 9,          // Physical HDMI port. e.g. HDMI 1
+    DISPLAY_PORT = 10,
+};
+
+struct TvInputDeviceInfo {
+    int32_t deviceId;
+    TvInputType type;
+    uint32_t portId;          // HDMI port ID number. e.g. 2 for HDMI 2
+    AudioDevice audioType;    // Audio device type. e.g AudioDevice::IN_HDMI
+    uint8_t[32] audioAddress; // Audio device address. "" if N/A. If the text
+                              // length is less than 32, the remaining part
+                              // must be filled with 0s.
+};
+
+enum TvInputEventType : int32_t {
+    /*
+     * Hardware notifies the framework that a device is available.
+     *
+     * Note that DEVICE_AVAILABLE and DEVICE_UNAVAILABLE events do not represent
+     * hotplug events (i.e. plugging cable into or out of the physical port).
+     * These events notify the framework whether the port is available or not.
+     * For a concrete example, when a user plugs in or pulls out the HDMI cable
+     * from a HDMI port, it does not generate DEVICE_AVAILABLE and/or
+     * DEVICE_UNAVAILABLE events. However, if a user inserts a pluggable USB
+     * tuner into the Android device, it must generate a DEVICE_AVAILABLE event
+     * and when the port is removed, it must generate a DEVICE_UNAVAILABLE
+     * event.
+     *
+     * For hotplug events, please see STREAM_CONFIGURATION_CHANGED for more
+     * details.
+     *
+     * HAL implementation must register devices by using this event when the
+     * device boots up. The framework must recognize device reported via this
+     * event only.
+     */
+    DEVICE_AVAILABLE = 1,
+
+    /*
+     * Hardware notifies the framework that a device is unavailable.
+     *
+     * HAL implementation must generate this event when a device registered
+     * by DEVICE_AVAILABLE is no longer available. For example,
+     * the event can indicate that a USB tuner is plugged out from the Android
+     * device.
+     *
+     * Note that this event is not for indicating cable plugged out of the port;
+     * for that purpose, the implementation must use
+     * STREAM_CONFIGURATION_CHANGED event. This event represents the port itself
+     * being no longer available.
+     */
+    DEVICE_UNAVAILABLE = 2,
+
+    /*
+     * Stream configurations are changed. Client must regard all open streams
+     * at the specific device are closed, and must call
+     * getStreamConfigurations() again, opening some of them if necessary.
+     *
+     * HAL implementation must generate this event when the available stream
+     * configurations change for any reason. A typical use case of this event
+     * is to notify the framework that the input signal has changed resolution,
+     * or that the cable is plugged out so that the number of available streams
+     * is 0.
+     *
+     * The implementation must use this event to indicate hotplug status of the
+     * port. the framework regards input devices with no available streams as
+     * disconnected, so the implementation can generate this event with no
+     * available streams to indicate that this device is disconnected, and vice
+     * versa.
+     */
+    STREAM_CONFIGURATIONS_CHANGED = 3,
+};
+
+struct TvInputEvent {
+    TvInputEventType type;
+    /*
+     * DEVICE_AVAILABLE: all fields are relevant.
+     * DEVICE_UNAVAILABLE: only deviceId is relevant.
+     * STREAM_CONFIGURATIONS_CHANGED: only deviceId is relevant.
+     */
+    TvInputDeviceInfo deviceInfo;
+};
+
+struct TvStreamConfig {
+    int32_t streamId;
+    uint32_t maxVideoWidth;  // Max width of the stream.
+    uint32_t maxVideoHeight; // Max height of the stream.
+};
diff --git a/tv/input/1.0/vts/Android.mk b/tv/input/1.0/vts/Android.mk
new file mode 100644
index 0000000..e0ad01e
--- /dev/null
+++ b/tv/input/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/tv_input/hidl/Android.mk
diff --git a/tv/input/1.0/vts/TvInput.vts b/tv/input/1.0/vts/TvInput.vts
new file mode 100644
index 0000000..73b322a
--- /dev/null
+++ b/tv/input/1.0/vts/TvInput.vts
@@ -0,0 +1,98 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "ITvInput"
+
+package: "android.hardware.tv.input"
+
+import: "android.hardware.tv.input@1.0::ITvInputCallback"
+import: "android.hardware.tv.input@1.0::types"
+
+interface: {
+    api: {
+        name: "setCallback"
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "ITvInputCallback"
+            is_callback: true
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+        callflow: {
+            next: "getStreamConfigurations"
+        }
+    }
+
+    api: {
+        name: "getStreamConfigurations"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::input::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::tv::input::V1_0::TvStreamConfig"
+            }
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        callflow: {
+            next: "openStream"
+            next: "getStreamConfigurations"
+            next: "closeStream"
+        }
+    }
+
+    api: {
+        name: "openStream"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::input::V1_0::Result"
+        }
+        return_type_hidl: {
+            type: TYPE_HANDLE
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        callflow: {
+            next: "closeStream"
+            next: "getStreamConfigurations"
+            next: "openStream"
+        }
+    }
+
+    api: {
+        name: "closeStream"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::tv::input::V1_0::Result"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+        callflow: {
+            next: "getStreamConfigurations"
+            next: "openStream"
+            next: "closeStream"
+        }
+    }
+
+}
diff --git a/tv/input/1.0/vts/TvInputCallback.vts b/tv/input/1.0/vts/TvInputCallback.vts
new file mode 100644
index 0000000..b1738a8
--- /dev/null
+++ b/tv/input/1.0/vts/TvInputCallback.vts
@@ -0,0 +1,18 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "ITvInputCallback"
+
+package: "android.hardware.tv.input"
+
+import: "android.hardware.tv.input@1.0::types"
+
+interface: {
+    api: {
+        name: "notify"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::tv::input::V1_0::TvInputEvent"
+        }
+    }
+
+}
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/__init__.py b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/__init__.py
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/Android.mk b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/__init__.py b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/__init__.py
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/Android.mk b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/Android.mk
new file mode 100644
index 0000000..2703d8c
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := TvInputHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/tv_input/hidl/host
+include test/vts/tools/build/Android.host_config.mk
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/AndroidTest.xml b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..8fdd72d
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS Tv Input HIDL HAL's host-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/TvInput.vts->/data/local/tmp/spec/TvInput.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/TvInputCallback.vts->/data/local/tmp/spec/TvInputCallback.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+        <option name="cleanup" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="TvInputHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/tv_input/hidl/host/TvInputHidlTest" />
+    </test>
+</configuration>
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/TvInputHidlTest.py b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/TvInputHidlTest.py
new file mode 100644
index 0000000..b5becd6
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/TvInputHidlTest.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+
+import logging
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+
+
+class TvInputHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """Two hello world test cases which use the shell driver."""
+
+    def setUpClass(self):
+        """Creates a mirror and init tv input hal."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        self.dut.hal.InitHidlHal(target_type="tv_input",
+                                 target_basepaths=["/system/lib64"],
+                                 target_version=1.0,
+                                 target_package="android.hardware.tv.input",
+                                 target_component_name="ITvInput",
+                                 bits=64 if self.dut.is64Bit else 32)
+
+        self.dut.shell.InvokeTerminal("one")
+
+    def testGetStreamConfigurations(self):
+        configs = self.dut.hal.tv_input.getStreamConfigurations(0)
+        logging.info('return value of getStreamConfigurations(0): %s', configs)
+
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/__init__.py b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host/__init__.py
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/Android.mk b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/Android.mk
new file mode 100644
index 0000000..514df20
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/Android.mk
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := TvInputHidlProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/tv_input/hidl/host_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/AndroidTest.xml b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/AndroidTest.xml
new file mode 100644
index 0000000..5b8e6f9
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?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.
+-->
+<configuration description="Config for VTS Tv Input HIDL HAL's host-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/TvInput.vts->/data/local/tmp/spec/TvInput.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/TvInputCallback.vts->/data/local/tmp/spec/TvInputCallback.vts" />
+        <option name="push" value="spec/hardware/interfaces/tv/input/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+        <option name="cleanup" value="true" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer">
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="TvInputHidlProfilingTest" />
+        <option name="test-case-path" value="vts/testcases/hal/tv_input/hidl/host/TvInputHidlTest" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/__init__.py b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/input/1.0/vts/functional/vts/testcases/hal/tv_input/hidl/host_profiling/__init__.py
diff --git a/tv/input/1.0/vts/types.vts b/tv/input/1.0/vts/types.vts
new file mode 100644
index 0000000..d03e065
--- /dev/null
+++ b/tv/input/1.0/vts/types.vts
@@ -0,0 +1,2096 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.tv.input"
+
+import: "android.hardware.audio.common@2.0::types"
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioHandleConsts"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "AUDIO_IO_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_MODULE_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_PORT_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "AUDIO_PATCH_HANDLE_NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::Uuid"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "timeLow"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "timeMid"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "versionAndTimeHigh"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "variantAndClockSeqHigh"
+        type: TYPE_SCALAR
+        scalar_type: "uint16_t"
+    }
+    struct_value: {
+        name: "node"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 6
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioStreamType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "MIN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "VOICE_CALL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SYSTEM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "RING"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "MUSIC"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ALARM"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NOTIFICATION"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "BLUETOOTH_SCO"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "ENFORCED_AUDIBLE"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "DTMF"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "TTS"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "ACCESSIBILITY"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "REROUTING"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "PATCH"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "PUBLIC_CNT"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "FOR_POLICY_CNT"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 13
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioSource"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MIC"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "VOICE_UPLINK"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VOICE_DOWNLINK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "VOICE_CALL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CAMCORDER"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "VOICE_RECOGNITION"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "VOICE_COMMUNICATION"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "REMOTE_SUBMIX"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "UNPROCESSED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "FM_TUNER"
+        scalar_value: {
+            int32_t: 1998
+        }
+        enumerator: "HOTWORD"
+        scalar_value: {
+            int32_t: 1999
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioSessionConsts"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OUTPUT_STAGE"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "OUTPUT_MIX"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ALLOCATE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioFormat"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            uint32_t: 4294967295
+        }
+        enumerator: "DEFAULT"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "PCM"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "MP3"
+        scalar_value: {
+            uint32_t: 16777216
+        }
+        enumerator: "AMR_NB"
+        scalar_value: {
+            uint32_t: 33554432
+        }
+        enumerator: "AMR_WB"
+        scalar_value: {
+            uint32_t: 50331648
+        }
+        enumerator: "AAC"
+        scalar_value: {
+            uint32_t: 67108864
+        }
+        enumerator: "HE_AAC_V1"
+        scalar_value: {
+            uint32_t: 83886080
+        }
+        enumerator: "HE_AAC_V2"
+        scalar_value: {
+            uint32_t: 100663296
+        }
+        enumerator: "VORBIS"
+        scalar_value: {
+            uint32_t: 117440512
+        }
+        enumerator: "OPUS"
+        scalar_value: {
+            uint32_t: 134217728
+        }
+        enumerator: "AC3"
+        scalar_value: {
+            uint32_t: 150994944
+        }
+        enumerator: "E_AC3"
+        scalar_value: {
+            uint32_t: 167772160
+        }
+        enumerator: "DTS"
+        scalar_value: {
+            uint32_t: 184549376
+        }
+        enumerator: "DTS_HD"
+        scalar_value: {
+            uint32_t: 201326592
+        }
+        enumerator: "IEC61937"
+        scalar_value: {
+            uint32_t: 218103808
+        }
+        enumerator: "DOLBY_TRUEHD"
+        scalar_value: {
+            uint32_t: 234881024
+        }
+        enumerator: "EVRC"
+        scalar_value: {
+            uint32_t: 268435456
+        }
+        enumerator: "EVRCB"
+        scalar_value: {
+            uint32_t: 285212672
+        }
+        enumerator: "EVRCWB"
+        scalar_value: {
+            uint32_t: 301989888
+        }
+        enumerator: "EVRCNW"
+        scalar_value: {
+            uint32_t: 318767104
+        }
+        enumerator: "AAC_ADIF"
+        scalar_value: {
+            uint32_t: 335544320
+        }
+        enumerator: "WMA"
+        scalar_value: {
+            uint32_t: 352321536
+        }
+        enumerator: "WMA_PRO"
+        scalar_value: {
+            uint32_t: 369098752
+        }
+        enumerator: "AMR_WB_PLUS"
+        scalar_value: {
+            uint32_t: 385875968
+        }
+        enumerator: "MP2"
+        scalar_value: {
+            uint32_t: 402653184
+        }
+        enumerator: "QCELP"
+        scalar_value: {
+            uint32_t: 419430400
+        }
+        enumerator: "DSD"
+        scalar_value: {
+            uint32_t: 436207616
+        }
+        enumerator: "FLAC"
+        scalar_value: {
+            uint32_t: 452984832
+        }
+        enumerator: "ALAC"
+        scalar_value: {
+            uint32_t: 469762048
+        }
+        enumerator: "APE"
+        scalar_value: {
+            uint32_t: 486539264
+        }
+        enumerator: "AAC_ADTS"
+        scalar_value: {
+            uint32_t: 503316480
+        }
+        enumerator: "SBC"
+        scalar_value: {
+            uint32_t: 520093696
+        }
+        enumerator: "APTX"
+        scalar_value: {
+            uint32_t: 536870912
+        }
+        enumerator: "APTX_HD"
+        scalar_value: {
+            uint32_t: 553648128
+        }
+        enumerator: "LDAC"
+        scalar_value: {
+            uint32_t: 570425344
+        }
+        enumerator: "MAIN_MASK"
+        scalar_value: {
+            uint32_t: 4278190080
+        }
+        enumerator: "SUB_MASK"
+        scalar_value: {
+            uint32_t: 16777215
+        }
+        enumerator: "PCM_SUB_16_BIT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "PCM_SUB_8_BIT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "PCM_SUB_32_BIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "PCM_SUB_8_24_BIT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PCM_SUB_FLOAT"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "PCM_SUB_24_BIT_PACKED"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "MP3_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "AMR_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "AAC_SUB_MAIN"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "AAC_SUB_LC"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "AAC_SUB_SSR"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "AAC_SUB_LTP"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "AAC_SUB_HE_V1"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "AAC_SUB_SCALABLE"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "AAC_SUB_ERLC"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "AAC_SUB_LD"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "AAC_SUB_HE_V2"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "AAC_SUB_ELD"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "VORBIS_SUB_NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "PCM_16_BIT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "PCM_8_BIT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "PCM_32_BIT"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "PCM_8_24_BIT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "PCM_FLOAT"
+        scalar_value: {
+            uint32_t: 5
+        }
+        enumerator: "PCM_24_BIT_PACKED"
+        scalar_value: {
+            uint32_t: 6
+        }
+        enumerator: "AAC_MAIN"
+        scalar_value: {
+            uint32_t: 67108865
+        }
+        enumerator: "AAC_LC"
+        scalar_value: {
+            uint32_t: 67108866
+        }
+        enumerator: "AAC_SSR"
+        scalar_value: {
+            uint32_t: 67108868
+        }
+        enumerator: "AAC_LTP"
+        scalar_value: {
+            uint32_t: 67108872
+        }
+        enumerator: "AAC_HE_V1"
+        scalar_value: {
+            uint32_t: 67108880
+        }
+        enumerator: "AAC_SCALABLE"
+        scalar_value: {
+            uint32_t: 67108896
+        }
+        enumerator: "AAC_ERLC"
+        scalar_value: {
+            uint32_t: 67108928
+        }
+        enumerator: "AAC_LD"
+        scalar_value: {
+            uint32_t: 67108992
+        }
+        enumerator: "AAC_HE_V2"
+        scalar_value: {
+            uint32_t: 67109120
+        }
+        enumerator: "AAC_ELD"
+        scalar_value: {
+            uint32_t: 67109376
+        }
+        enumerator: "AAC_ADTS_MAIN"
+        scalar_value: {
+            uint32_t: 503316481
+        }
+        enumerator: "AAC_ADTS_LC"
+        scalar_value: {
+            uint32_t: 503316482
+        }
+        enumerator: "AAC_ADTS_SSR"
+        scalar_value: {
+            uint32_t: 503316484
+        }
+        enumerator: "AAC_ADTS_LTP"
+        scalar_value: {
+            uint32_t: 503316488
+        }
+        enumerator: "AAC_ADTS_HE_V1"
+        scalar_value: {
+            uint32_t: 503316496
+        }
+        enumerator: "AAC_ADTS_SCALABLE"
+        scalar_value: {
+            uint32_t: 503316512
+        }
+        enumerator: "AAC_ADTS_ERLC"
+        scalar_value: {
+            uint32_t: 503316544
+        }
+        enumerator: "AAC_ADTS_LD"
+        scalar_value: {
+            uint32_t: 503316608
+        }
+        enumerator: "AAC_ADTS_HE_V2"
+        scalar_value: {
+            uint32_t: 503316736
+        }
+        enumerator: "AAC_ADTS_ELD"
+        scalar_value: {
+            uint32_t: 503316992
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::FixedChannelCount"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FCC_2"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FCC_8"
+        scalar_value: {
+            int32_t: 8
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "REPRESENTATION_POSITION"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "REPRESENTATION_INDEX"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "INVALID"
+        scalar_value: {
+            uint32_t: 3221225472
+        }
+        enumerator: "OUT_FRONT_LEFT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_FRONT_RIGHT"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "OUT_FRONT_CENTER"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "OUT_LOW_FREQUENCY"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "OUT_BACK_LEFT"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "OUT_BACK_RIGHT"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "OUT_FRONT_LEFT_OF_CENTER"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "OUT_FRONT_RIGHT_OF_CENTER"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "OUT_BACK_CENTER"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "OUT_SIDE_LEFT"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "OUT_SIDE_RIGHT"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_TOP_CENTER"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "OUT_TOP_FRONT_LEFT"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "OUT_TOP_FRONT_CENTER"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "OUT_TOP_FRONT_RIGHT"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "OUT_TOP_BACK_LEFT"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "OUT_TOP_BACK_CENTER"
+        scalar_value: {
+            uint32_t: 65536
+        }
+        enumerator: "OUT_TOP_BACK_RIGHT"
+        scalar_value: {
+            uint32_t: 131072
+        }
+        enumerator: "OUT_MONO"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_STEREO"
+        scalar_value: {
+            uint32_t: 3
+        }
+        enumerator: "OUT_2POINT1"
+        scalar_value: {
+            uint32_t: 11
+        }
+        enumerator: "OUT_QUAD"
+        scalar_value: {
+            uint32_t: 51
+        }
+        enumerator: "OUT_QUAD_BACK"
+        scalar_value: {
+            uint32_t: 51
+        }
+        enumerator: "OUT_QUAD_SIDE"
+        scalar_value: {
+            uint32_t: 1539
+        }
+        enumerator: "OUT_SURROUND"
+        scalar_value: {
+            uint32_t: 263
+        }
+        enumerator: "OUT_PENTA"
+        scalar_value: {
+            uint32_t: 55
+        }
+        enumerator: "OUT_5POINT1"
+        scalar_value: {
+            uint32_t: 63
+        }
+        enumerator: "OUT_5POINT1_BACK"
+        scalar_value: {
+            uint32_t: 63
+        }
+        enumerator: "OUT_5POINT1_SIDE"
+        scalar_value: {
+            uint32_t: 1551
+        }
+        enumerator: "OUT_6POINT1"
+        scalar_value: {
+            uint32_t: 319
+        }
+        enumerator: "OUT_7POINT1"
+        scalar_value: {
+            uint32_t: 1599
+        }
+        enumerator: "OUT_ALL"
+        scalar_value: {
+            uint32_t: 262143
+        }
+        enumerator: "IN_LEFT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "IN_RIGHT"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "IN_FRONT"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "IN_BACK"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "IN_LEFT_PROCESSED"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "IN_RIGHT_PROCESSED"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "IN_FRONT_PROCESSED"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "IN_BACK_PROCESSED"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "IN_PRESSURE"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "IN_X_AXIS"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "IN_Y_AXIS"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "IN_Z_AXIS"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "IN_VOICE_UPLINK"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "IN_VOICE_DNLINK"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "IN_MONO"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "IN_STEREO"
+        scalar_value: {
+            uint32_t: 12
+        }
+        enumerator: "IN_FRONT_BACK"
+        scalar_value: {
+            uint32_t: 48
+        }
+        enumerator: "IN_VOICE_UPLINK_MONO"
+        scalar_value: {
+            uint32_t: 16400
+        }
+        enumerator: "IN_VOICE_DNLINK_MONO"
+        scalar_value: {
+            uint32_t: 32784
+        }
+        enumerator: "IN_VOICE_CALL_MONO"
+        scalar_value: {
+            uint32_t: 49168
+        }
+        enumerator: "IN_ALL"
+        scalar_value: {
+            uint32_t: 65532
+        }
+        enumerator: "COUNT_MAX"
+        scalar_value: {
+            uint32_t: 30
+        }
+        enumerator: "INDEX_HDR"
+        scalar_value: {
+            uint32_t: 2147483648
+        }
+        enumerator: "INDEX_MASK_1"
+        scalar_value: {
+            uint32_t: 2147483649
+        }
+        enumerator: "INDEX_MASK_2"
+        scalar_value: {
+            uint32_t: 2147483651
+        }
+        enumerator: "INDEX_MASK_3"
+        scalar_value: {
+            uint32_t: 2147483655
+        }
+        enumerator: "INDEX_MASK_4"
+        scalar_value: {
+            uint32_t: 2147483663
+        }
+        enumerator: "INDEX_MASK_5"
+        scalar_value: {
+            uint32_t: 2147483679
+        }
+        enumerator: "INDEX_MASK_6"
+        scalar_value: {
+            uint32_t: 2147483711
+        }
+        enumerator: "INDEX_MASK_7"
+        scalar_value: {
+            uint32_t: 2147483775
+        }
+        enumerator: "INDEX_MASK_8"
+        scalar_value: {
+            uint32_t: 2147483903
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioInterleave"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "LEFT"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RIGHT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            int32_t: -2
+        }
+        enumerator: "CURRENT"
+        scalar_value: {
+            int32_t: -1
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RINGTONE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "IN_CALL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "IN_COMMUNICATION"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioDevice"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "BIT_IN"
+        scalar_value: {
+            uint32_t: 2147483648
+        }
+        enumerator: "BIT_DEFAULT"
+        scalar_value: {
+            uint32_t: 1073741824
+        }
+        enumerator: "OUT_EARPIECE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "OUT_SPEAKER"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "OUT_WIRED_HEADSET"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "OUT_WIRED_HEADPHONE"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "OUT_BLUETOOTH_SCO"
+        scalar_value: {
+            uint32_t: 16
+        }
+        enumerator: "OUT_BLUETOOTH_SCO_HEADSET"
+        scalar_value: {
+            uint32_t: 32
+        }
+        enumerator: "OUT_BLUETOOTH_SCO_CARKIT"
+        scalar_value: {
+            uint32_t: 64
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP"
+        scalar_value: {
+            uint32_t: 128
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP_HEADPHONES"
+        scalar_value: {
+            uint32_t: 256
+        }
+        enumerator: "OUT_BLUETOOTH_A2DP_SPEAKER"
+        scalar_value: {
+            uint32_t: 512
+        }
+        enumerator: "OUT_AUX_DIGITAL"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_HDMI"
+        scalar_value: {
+            uint32_t: 1024
+        }
+        enumerator: "OUT_ANLG_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2048
+        }
+        enumerator: "OUT_DGTL_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 4096
+        }
+        enumerator: "OUT_USB_ACCESSORY"
+        scalar_value: {
+            uint32_t: 8192
+        }
+        enumerator: "OUT_USB_DEVICE"
+        scalar_value: {
+            uint32_t: 16384
+        }
+        enumerator: "OUT_REMOTE_SUBMIX"
+        scalar_value: {
+            uint32_t: 32768
+        }
+        enumerator: "OUT_TELEPHONY_TX"
+        scalar_value: {
+            uint32_t: 65536
+        }
+        enumerator: "OUT_LINE"
+        scalar_value: {
+            uint32_t: 131072
+        }
+        enumerator: "OUT_HDMI_ARC"
+        scalar_value: {
+            uint32_t: 262144
+        }
+        enumerator: "OUT_SPDIF"
+        scalar_value: {
+            uint32_t: 524288
+        }
+        enumerator: "OUT_FM"
+        scalar_value: {
+            uint32_t: 1048576
+        }
+        enumerator: "OUT_AUX_LINE"
+        scalar_value: {
+            uint32_t: 2097152
+        }
+        enumerator: "OUT_SPEAKER_SAFE"
+        scalar_value: {
+            uint32_t: 4194304
+        }
+        enumerator: "OUT_IP"
+        scalar_value: {
+            uint32_t: 8388608
+        }
+        enumerator: "OUT_BUS"
+        scalar_value: {
+            uint32_t: 16777216
+        }
+        enumerator: "OUT_PROXY"
+        scalar_value: {
+            uint32_t: 33554432
+        }
+        enumerator: "OUT_DEFAULT"
+        scalar_value: {
+            uint32_t: 1073741824
+        }
+        enumerator: "OUT_ALL"
+        scalar_value: {
+            uint32_t: 1140850687
+        }
+        enumerator: "OUT_ALL_A2DP"
+        scalar_value: {
+            uint32_t: 896
+        }
+        enumerator: "OUT_ALL_SCO"
+        scalar_value: {
+            uint32_t: 112
+        }
+        enumerator: "OUT_ALL_USB"
+        scalar_value: {
+            uint32_t: 24576
+        }
+        enumerator: "IN_COMMUNICATION"
+        scalar_value: {
+            uint32_t: 2147483649
+        }
+        enumerator: "IN_AMBIENT"
+        scalar_value: {
+            uint32_t: 2147483650
+        }
+        enumerator: "IN_BUILTIN_MIC"
+        scalar_value: {
+            uint32_t: 2147483652
+        }
+        enumerator: "IN_BLUETOOTH_SCO_HEADSET"
+        scalar_value: {
+            uint32_t: 2147483656
+        }
+        enumerator: "IN_WIRED_HEADSET"
+        scalar_value: {
+            uint32_t: 2147483664
+        }
+        enumerator: "IN_AUX_DIGITAL"
+        scalar_value: {
+            uint32_t: 2147483680
+        }
+        enumerator: "IN_HDMI"
+        scalar_value: {
+            uint32_t: 2147483680
+        }
+        enumerator: "IN_VOICE_CALL"
+        scalar_value: {
+            uint32_t: 2147483712
+        }
+        enumerator: "IN_TELEPHONY_RX"
+        scalar_value: {
+            uint32_t: 2147483712
+        }
+        enumerator: "IN_BACK_MIC"
+        scalar_value: {
+            uint32_t: 2147483776
+        }
+        enumerator: "IN_REMOTE_SUBMIX"
+        scalar_value: {
+            uint32_t: 2147483904
+        }
+        enumerator: "IN_ANLG_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2147484160
+        }
+        enumerator: "IN_DGTL_DOCK_HEADSET"
+        scalar_value: {
+            uint32_t: 2147484672
+        }
+        enumerator: "IN_USB_ACCESSORY"
+        scalar_value: {
+            uint32_t: 2147485696
+        }
+        enumerator: "IN_USB_DEVICE"
+        scalar_value: {
+            uint32_t: 2147487744
+        }
+        enumerator: "IN_FM_TUNER"
+        scalar_value: {
+            uint32_t: 2147491840
+        }
+        enumerator: "IN_TV_TUNER"
+        scalar_value: {
+            uint32_t: 2147500032
+        }
+        enumerator: "IN_LINE"
+        scalar_value: {
+            uint32_t: 2147516416
+        }
+        enumerator: "IN_SPDIF"
+        scalar_value: {
+            uint32_t: 2147549184
+        }
+        enumerator: "IN_BLUETOOTH_A2DP"
+        scalar_value: {
+            uint32_t: 2147614720
+        }
+        enumerator: "IN_LOOPBACK"
+        scalar_value: {
+            uint32_t: 2147745792
+        }
+        enumerator: "IN_IP"
+        scalar_value: {
+            uint32_t: 2148007936
+        }
+        enumerator: "IN_BUS"
+        scalar_value: {
+            uint32_t: 2148532224
+        }
+        enumerator: "IN_PROXY"
+        scalar_value: {
+            uint32_t: 2164260864
+        }
+        enumerator: "IN_DEFAULT"
+        scalar_value: {
+            uint32_t: 3221225472
+        }
+        enumerator: "IN_ALL"
+        scalar_value: {
+            uint32_t: 3240099839
+        }
+        enumerator: "IN_ALL_SCO"
+        scalar_value: {
+            uint32_t: 2147483656
+        }
+        enumerator: "IN_ALL_USB"
+        scalar_value: {
+            uint32_t: 2147489792
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioOutputFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DIRECT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "PRIMARY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FAST"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "DEEP_BUFFER"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "COMPRESS_OFFLOAD"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "NON_BLOCKING"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "HW_AV_SYNC"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "TTS"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "RAW"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "SYNC"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "IEC958_NONAUDIO"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "DIRECT_PCM"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "MMAP_NOIRQ"
+        scalar_value: {
+            int32_t: 16384
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioInputFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "FAST"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "HW_HOTWORD"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "RAW"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SYNC"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "MMAP_NOIRQ"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioUsage"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MEDIA"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "VOICE_COMMUNICATION"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VOICE_COMMUNICATION_SIGNALLING"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ALARM"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NOTIFICATION"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "NOTIFICATION_TELEPHONY_RINGTONE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_REQUEST"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_INSTANT"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "NOTIFICATION_COMMUNICATION_DELAYED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "NOTIFICATION_EVENT"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "ASSISTANCE_ACCESSIBILITY"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "ASSISTANCE_NAVIGATION_GUIDANCE"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "ASSISTANCE_SONIFICATION"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "GAME"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "VIRTUAL_SOURCE"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "CNT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MAX"
+        scalar_value: {
+            int32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioOffloadInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "streamType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioStreamType"
+    }
+    struct_value: {
+        name: "bitRatePerSecond"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "durationMicroseconds"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "hasVideo"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "isStreaming"
+        type: TYPE_SCALAR
+        scalar_type: "bool_t"
+    }
+    struct_value: {
+        name: "bitWidth"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "bufferSize"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "usage"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioUsage"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "offloadInfo"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioOffloadInfo"
+    }
+    struct_value: {
+        name: "frameCount"
+        type: TYPE_SCALAR
+        scalar_type: "uint64_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "JOINT"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "CHANNELS"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "RAMP"
+        scalar_value: {
+            uint32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGain"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "mode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "minValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "defaultValue"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "stepValue"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "minRampMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "maxRampMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioGainConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "index"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "mode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainMode"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "values"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+    struct_value: {
+        name: "rampDurationMs"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SOURCE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SINK"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DEVICE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MIX"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SESSION"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigDeviceExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioDevice"
+    }
+    struct_value: {
+        name: "address"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigSessionExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "session"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfigMask"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "SAMPLE_RATE"
+        scalar_value: {
+            uint32_t: 1
+        }
+        enumerator: "CHANNEL_MASK"
+        scalar_value: {
+            uint32_t: 2
+        }
+        enumerator: "FORMAT"
+        scalar_value: {
+            uint32_t: 4
+        }
+        enumerator: "GAIN"
+        scalar_value: {
+            uint32_t: 8
+        }
+        enumerator: "ALL"
+        scalar_value: {
+            uint32_t: 15
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortConfig"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext"
+        type: TYPE_UNION
+        sub_union: {
+            name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt"
+            type: TYPE_STRUCT
+            sub_struct: {
+                name: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt::UseCase"
+                type: TYPE_UNION
+                union_value: {
+                    name: "stream"
+                    type: TYPE_ENUM
+                    predefined_type: "::android::hardware::audio::common::V2_0::AudioStreamType"
+                }
+                union_value: {
+                    name: "source"
+                    type: TYPE_ENUM
+                    predefined_type: "::android::hardware::audio::common::V2_0::AudioSource"
+                }
+            }
+            struct_value: {
+                name: "hwModule"
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+            struct_value: {
+                name: "ioHandle"
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+            struct_value: {
+                name: "useCase"
+                type: TYPE_UNION
+                predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt::UseCase"
+            }
+        }
+        union_value: {
+            name: "device"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigDeviceExt"
+        }
+        union_value: {
+            name: "mix"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext::AudioPortConfigMixExt"
+        }
+        union_value: {
+            name: "session"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigSessionExt"
+        }
+    }
+    struct_value: {
+        name: "id"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "configMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfigMask"
+    }
+    struct_value: {
+        name: "sampleRateHz"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "channelMask"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+    }
+    struct_value: {
+        name: "format"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+    }
+    struct_value: {
+        name: "gain"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioGainConfig"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortType"
+    }
+    struct_value: {
+        name: "role"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    }
+    struct_value: {
+        name: "ext"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig::Ext"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortDeviceExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioDevice"
+    }
+    struct_value: {
+        name: "address"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioMixLatencyClass"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "LOW"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NORMAL"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortMixExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "hwModule"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "ioHandle"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "latencyClass"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioMixLatencyClass"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPortSessionExt"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "session"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::audio::common::V2_0::AudioPort"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::audio::common::V2_0::AudioPort::Ext"
+        type: TYPE_UNION
+        union_value: {
+            name: "device"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortDeviceExt"
+        }
+        union_value: {
+            name: "mix"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortMixExt"
+        }
+        union_value: {
+            name: "session"
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioPortSessionExt"
+        }
+    }
+    struct_value: {
+        name: "id"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "role"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortRole"
+    }
+    struct_value: {
+        name: "name"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "sampleRates"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+    struct_value: {
+        name: "channelMasks"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioChannelMask"
+        }
+    }
+    struct_value: {
+        name: "formats"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioFormat"
+        }
+    }
+    struct_value: {
+        name: "gains"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::audio::common::V2_0::AudioGain"
+        }
+    }
+    struct_value: {
+        name: "activeConfig"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortConfig"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPortType"
+    }
+    struct_value: {
+        name: "ext"
+        type: TYPE_UNION
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioPort::Ext"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::Result"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "UNKNOWN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NO_RESOURCE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "INVALID_ARGUMENTS"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "INVALID_STATE"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::TvInputType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OTHER"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TUNER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "COMPOSITE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SVIDEO"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SCART"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "COMPONENT"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "VGA"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "DVI"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "HDMI"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "DISPLAY_PORT"
+        scalar_value: {
+            int32_t: 10
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::TvInputDeviceInfo"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "deviceId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::tv::input::V1_0::TvInputType"
+    }
+    struct_value: {
+        name: "portId"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "audioType"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::audio::common::V2_0::AudioDevice"
+    }
+    struct_value: {
+        name: "audioAddress"
+        type: TYPE_ARRAY
+        vector_value: {
+            vector_size: 32
+            type: TYPE_SCALAR
+            scalar_type: "uint8_t"
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::TvInputEventType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DEVICE_AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DEVICE_UNAVAILABLE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "STREAM_CONFIGURATIONS_CHANGED"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::TvInputEvent"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "type"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::tv::input::V1_0::TvInputEventType"
+    }
+    struct_value: {
+        name: "deviceInfo"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::tv::input::V1_0::TvInputDeviceInfo"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::tv::input::V1_0::TvStreamConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "streamId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxVideoWidth"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+    struct_value: {
+        name: "maxVideoHeight"
+        type: TYPE_SCALAR
+        scalar_type: "uint32_t"
+    }
+}
+
diff --git a/tv/input/Android.mk b/tv/input/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/tv/input/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/update-base-files.sh b/update-base-files.sh
new file mode 100755
index 0000000..1eb6b51
--- /dev/null
+++ b/update-base-files.sh
@@ -0,0 +1,43 @@
+#!/bin/bash
+
+if [ ! -d hardware/interfaces ] ; then
+  echo "Where is hardware/interfaces?";
+  exit 1;
+fi
+
+if [ ! -d system/libhidl/transport ] ; then
+  echo "Where is system/libhidl/transport?";
+  exit 1;
+fi
+
+echo "WARNING: This script changes files in many places."
+
+# These files only exist to facilitate the easy transition to hidl.
+
+options="-Lexport-header \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport"
+
+# hardware/libhardware
+hidl-gen $options \
+         -o hardware/libhardware/include/hardware/sensors-base.h \
+         android.hardware.sensors@1.0
+hidl-gen $options \
+         -o hardware/libhardware/include/hardware/nfc-base.h \
+         android.hardware.nfc@1.0
+hidl-gen $options \
+         -o hardware/libhardware/include/hardware/gnss-base.h \
+         android.hardware.gnss@1.0
+
+# system/core
+hidl-gen $options \
+         -o system/core/include/system/graphics-base.h \
+         android.hardware.graphics.common@1.0
+
+# system/media
+hidl-gen $options \
+         -o system/media/audio/include/system/audio-base.h \
+         android.hardware.audio.common@2.0
+hidl-gen $options \
+         -o system/media/audio/include/system/audio_effect-base.h \
+         android.hardware.audio.effect@2.0
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
new file mode 100644
index 0000000..8b84a4a
--- /dev/null
+++ b/usb/1.0/Android.bp
@@ -0,0 +1,64 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.usb@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.usb@1.0",
+    srcs: [
+        "types.hal",
+        "IUsb.hal",
+        "IUsbCallback.hal",
+    ],
+    out: [
+        "android/hardware/usb/1.0/types.cpp",
+        "android/hardware/usb/1.0/UsbAll.cpp",
+        "android/hardware/usb/1.0/UsbCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.usb@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.usb@1.0",
+    srcs: [
+        "types.hal",
+        "IUsb.hal",
+        "IUsbCallback.hal",
+    ],
+    out: [
+        "android/hardware/usb/1.0/types.h",
+        "android/hardware/usb/1.0/IUsb.h",
+        "android/hardware/usb/1.0/IHwUsb.h",
+        "android/hardware/usb/1.0/BnHwUsb.h",
+        "android/hardware/usb/1.0/BpHwUsb.h",
+        "android/hardware/usb/1.0/BsUsb.h",
+        "android/hardware/usb/1.0/IUsbCallback.h",
+        "android/hardware/usb/1.0/IHwUsbCallback.h",
+        "android/hardware/usb/1.0/BnHwUsbCallback.h",
+        "android/hardware/usb/1.0/BpHwUsbCallback.h",
+        "android/hardware/usb/1.0/BsUsbCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.usb@1.0",
+    generated_sources: ["android.hardware.usb@1.0_genc++"],
+    generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/usb/1.0/Android.mk b/usb/1.0/Android.mk
new file mode 100644
index 0000000..0eded5b
--- /dev/null
+++ b/usb/1.0/Android.mk
@@ -0,0 +1,427 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (PortDataRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortDataRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortDataRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortMode)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortPowerRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortPowerRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortPowerRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRoleType)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRoleType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortRoleType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortStatus)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsb.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsb.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsb.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::IUsb
+
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsbCallback.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsbCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::IUsbCallback
+
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (PortDataRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortDataRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortDataRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortMode)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortPowerRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortPowerRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortPowerRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRole)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRole.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortRole
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortRoleType)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortRoleType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortRoleType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (PortStatus)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/PortStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.PortStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsb.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsb.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsb.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::IUsb
+
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IUsbCallback.hal
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/IUsbCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IUsbCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0::IUsbCallback
+
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.usb@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/usb/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IUsb.hal
+$(GEN): $(LOCAL_PATH)/IUsbCallback.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.usb@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/usb/1.0/IUsb.hal b/usb/1.0/IUsb.hal
new file mode 100644
index 0000000..965326a
--- /dev/null
+++ b/usb/1.0/IUsb.hal
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package android.hardware.usb@1.0;
+
+import IUsbCallback;
+
+interface IUsb {
+    /*
+     * This function is used to change the port role of a specific port.
+     * For example, when PD_SWAP or PR_SWAP is supported.
+     * This is function is asynchronous. The status of the role switch
+     * will be informed through IUsbCallback object's notifyPortStatusChange
+     * method.
+     *
+     * @param portName name of the port for which the role has to be changed
+     * @param role the new port role.
+     */
+    oneway switchRole(string portName, PortRole role);
+
+    /*
+     * This function is used to register a callback function which is
+     * called by the HAL whenever there is a change in the port state.
+     * i.e. DATA_ROLE, POWER_ROLE or MODE.
+     *
+     * Also the same callback object would be called to inform the caller
+     * of the roleSwitch status.
+     *
+     * @param callback IUsbCallback object used to convey status to the
+     * userspace.
+     */
+    oneway setCallback(IUsbCallback callback);
+
+    /*
+     * This functions is used to request the hal for the current status
+     * status of the Type-C ports. This method is async/oneway. The result of the
+     * query would be sent through the IUsbCallback object's notifyRoleSwitchStatus
+     * to the caller. This api would would let the caller know of the number
+     * of type-c ports that are present and their connection status through the
+     * PortStatus type.
+     */
+    oneway queryPortStatus();
+};
+
diff --git a/usb/1.0/IUsbCallback.hal b/usb/1.0/IUsbCallback.hal
new file mode 100644
index 0000000..b665ba3
--- /dev/null
+++ b/usb/1.0/IUsbCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.hardware.usb@1.0;
+
+/*
+ * Callback object used for all the IUsb async methods which expects a result.
+ * Caller is expected to register the callback object using setCallback method
+ * to receive updates on the PortStatus.
+ */
+interface IUsbCallback {
+    /*
+     * Used to convey the current port status to the caller.
+     * Called either when PortState changes due to the port partner (or)
+     * when caller requested for the PortStatus update through queryPortStatus.
+     *
+     * @param currentPortStatus vector object of current status of all the
+     * typeC ports in the device.
+     * @param retval SUCCESS when query was done successfully.
+     * ERROR otherwise.
+     */
+    oneway notifyPortStatusChange(vec<PortStatus> currentPortStatus, Status retval);
+
+    /*
+     * Used to notify the result of the switchRole call to the caller.
+     *
+     * @param portName name of the port for which the roleswap is requested.
+     * @param newRole the new role requested by the caller.
+     * @param retval SUCCESS if the role switch succeeded. FAILURE otherwise.
+     */
+    oneway notifyRoleSwitchStatus(string portName, PortRole newRole, Status retval);
+};
diff --git a/usb/1.0/default/Android.mk b/usb/1.0/default/Android.mk
new file mode 100644
index 0000000..09d7ce7
--- /dev/null
+++ b/usb/1.0/default/Android.mk
@@ -0,0 +1,21 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_MODULE := android.hardware.usb@1.0-service
+LOCAL_INIT_RC := android.hardware.usb@1.0-service.rc
+LOCAL_SRC_FILES := \
+    service.cpp \
+    Usb.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libhwbinder \
+    libutils \
+    libhardware \
+    android.hardware.usb@1.0 \
+
+include $(BUILD_EXECUTABLE)
diff --git a/usb/1.0/default/Usb.cpp b/usb/1.0/default/Usb.cpp
new file mode 100644
index 0000000..f46ff66
--- /dev/null
+++ b/usb/1.0/default/Usb.cpp
@@ -0,0 +1,428 @@
+/*
+ * 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.
+ */
+#include <dirent.h>
+#include <iostream>
+#include <fstream>
+#include <pthread.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cutils/uevent.h>
+#include <sys/epoll.h>
+#include <utils/Errors.h>
+#include <utils/StrongPointer.h>
+
+#include "Usb.h"
+
+namespace android {
+namespace hardware {
+namespace usb {
+namespace V1_0 {
+namespace implementation {
+
+int32_t readFile(std::string filename, std::string& contents) {
+    std::ifstream file(filename);
+
+    if (file.is_open()) {
+        getline(file, contents);
+        file.close();
+        return 0;
+    }
+    return -1;
+}
+
+std::string appendRoleNodeHelper(const std::string portName, PortRoleType type) {
+    std::string node("/sys/class/dual_role_usb/" + portName);
+
+    switch(type) {
+        case PortRoleType::DATA_ROLE:
+            return node + "/data_role";
+        case PortRoleType::POWER_ROLE:
+            return node + "/power_role";
+        default:
+            return node + "/mode";
+    }
+}
+
+std::string convertRoletoString(PortRole role) {
+    if (role.type == PortRoleType::POWER_ROLE) {
+        if (role.role == static_cast<uint32_t> (PortPowerRole::SOURCE))
+            return "source";
+        else if (role.role ==  static_cast<uint32_t> (PortPowerRole::SINK))
+            return "sink";
+    } else if (role.type == PortRoleType::DATA_ROLE) {
+        if (role.role == static_cast<uint32_t> (PortDataRole::HOST))
+            return "host";
+        if (role.role == static_cast<uint32_t> (PortDataRole::DEVICE))
+            return "device";
+    } else if (role.type == PortRoleType::MODE) {
+        if (role.role == static_cast<uint32_t> (PortMode::UFP))
+            return "ufp";
+        if (role.role == static_cast<uint32_t> (PortMode::DFP))
+            return "dfp";
+    }
+    return "none";
+}
+
+Return<void> Usb::switchRole(const hidl_string& portName,
+        const PortRole& newRole) {
+    std::string filename = appendRoleNodeHelper(std::string(portName.c_str()),
+        newRole.type);
+    std::ofstream file(filename);
+    std::string written;
+
+    ALOGI("filename write: %s role:%d", filename.c_str(), newRole.role);
+
+    if (file.is_open()) {
+        file << convertRoletoString(newRole).c_str();
+        file.close();
+        if (!readFile(filename, written)) {
+            ALOGI("written: %s", written.c_str());
+            if (written == convertRoletoString(newRole)) {
+                ALOGI("Role switch successfull");
+                Return<void> ret =
+                    mCallback->notifyRoleSwitchStatus(portName, newRole,
+                    Status::SUCCESS);
+                if (!ret.isOk())
+                    ALOGE("RoleSwitchStatus error %s",
+                        ret.description().c_str());
+            }
+        }
+    }
+
+    Return<void> ret = mCallback->notifyRoleSwitchStatus(portName, newRole, Status::ERROR);
+    if (!ret.isOk())
+        ALOGE("RoleSwitchStatus error %s", ret.description().c_str());
+
+    return Void();
+}
+
+Status getCurrentRoleHelper(std::string portName,
+        PortRoleType type, uint32_t &currentRole)  {
+    std::string filename;
+    std::string roleName;
+
+    if (type == PortRoleType::POWER_ROLE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/power_role";
+        currentRole = static_cast<uint32_t>(PortPowerRole::NONE);
+    } else if (type == PortRoleType::DATA_ROLE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/data_role";
+        currentRole = static_cast<uint32_t> (PortDataRole::NONE);
+    } else if (type == PortRoleType::MODE) {
+        filename = "/sys/class/dual_role_usb/" +
+            portName + "/mode";
+        currentRole = static_cast<uint32_t> (PortMode::NONE);
+    }
+
+    if (readFile(filename, roleName)) {
+        ALOGE("getCurrentRole: Failed to open filesystem node");
+        return Status::ERROR;
+    }
+
+    if (roleName == "dfp")
+        currentRole = static_cast<uint32_t> (PortMode::DFP);
+    else if (roleName == "ufp")
+        currentRole = static_cast<uint32_t> (PortMode::UFP);
+    else if (roleName == "source")
+        currentRole = static_cast<uint32_t> (PortPowerRole::SOURCE);
+    else if (roleName == "sink")
+        currentRole = static_cast<uint32_t> (PortPowerRole::SINK);
+    else if (roleName == "host")
+        currentRole = static_cast<uint32_t> (PortDataRole::HOST);
+    else if (roleName == "device")
+        currentRole = static_cast<uint32_t> (PortDataRole::DEVICE);
+    else if (roleName != "none") {
+         /* case for none has already been addressed.
+          * so we check if the role isnt none.
+          */
+        return Status::UNRECOGNIZED_ROLE;
+    }
+    return Status::SUCCESS;
+}
+
+Status getTypeCPortNamesHelper(std::vector<std::string>& names) {
+    DIR *dp;
+
+    dp = opendir("/sys/class/dual_role_usb");
+    if (dp != NULL)
+    {
+rescan:
+        int32_t ports = 0;
+        int32_t current = 0;
+        struct dirent *ep;
+
+        while ((ep = readdir (dp))) {
+            if (ep->d_type == DT_LNK) {
+                ports++;
+            }
+        }
+        names.resize(ports);
+        rewinddir(dp);
+
+        while ((ep = readdir (dp))) {
+            /* Check to see if new ports were added since the first pass. */
+            if (current >= ports) {
+               rewinddir(dp);
+               goto rescan;
+            }
+
+            if (ep->d_type == DT_LNK) {
+                names[current++] = ep->d_name;
+            }
+        }
+
+        closedir (dp);
+        return Status::SUCCESS;
+    }
+
+    ALOGE("Failed to open /sys/class/dual_role_usb");
+    return Status::ERROR;
+}
+
+bool canSwitchRoleHelper(const std::string portName, PortRoleType type)  {
+    std::string filename = appendRoleNodeHelper(portName, type);
+    std::ofstream file(filename);
+
+    if (file.is_open()) {
+        file.close();
+        return true;
+    }
+    return false;
+}
+
+Status getPortModeHelper(const std::string portName, PortMode& portMode)  {
+    std::string filename = "/sys/class/dual_role_usb/" +
+    std::string(portName.c_str()) + "/supported_modes";
+    std::string modes;
+
+    if (readFile(filename, modes)) {
+        ALOGE("getSupportedRoles: Failed to open filesystem node");
+        return Status::ERROR;
+    }
+
+    if (modes == "ufp dfp")
+        portMode = PortMode::DRP;
+    else  if (modes == "ufp")
+        portMode = PortMode::UFP;
+    else if  (modes == "dfp")
+        portMode = PortMode::DFP;
+    else
+        return Status::UNRECOGNIZED_ROLE;
+
+        return Status::SUCCESS;
+}
+
+Status getPortStatusHelper (hidl_vec<PortStatus>& currentPortStatus) {
+    std::vector<std::string> names;
+    Status result = getTypeCPortNamesHelper(names);
+
+    if (result == Status::SUCCESS) {
+        currentPortStatus.resize(names.size());
+        for(std::vector<std::string>::size_type i = 0; i != names.size(); i++) {
+            ALOGI("%s", names[i].c_str());
+            currentPortStatus[i].portName = names[i];
+
+            uint32_t currentRole;
+            if (getCurrentRoleHelper(names[i], PortRoleType::POWER_ROLE,
+                    currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentPowerRole =
+                static_cast<PortPowerRole> (currentRole);
+            } else {
+                ALOGE("Error while retreiving portNames");
+                goto done;
+            }
+
+            if (getCurrentRoleHelper(names[i],
+                    PortRoleType::DATA_ROLE, currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentDataRole =
+                        static_cast<PortDataRole> (currentRole);
+            } else {
+                ALOGE("Error while retreiving current port role");
+                goto done;
+            }
+
+            if (getCurrentRoleHelper(names[i], PortRoleType::MODE,
+                    currentRole) == Status::SUCCESS) {
+                currentPortStatus[i].currentMode =
+                    static_cast<PortMode> (currentRole);
+            } else {
+                ALOGE("Error while retreiving current data role");
+                goto done;
+            }
+
+            currentPortStatus[i].canChangeMode =
+                canSwitchRoleHelper(names[i], PortRoleType::MODE);
+            currentPortStatus[i].canChangeDataRole =
+                canSwitchRoleHelper(names[i], PortRoleType::DATA_ROLE);
+            currentPortStatus[i].canChangePowerRole =
+                canSwitchRoleHelper(names[i], PortRoleType::POWER_ROLE);
+
+            ALOGI("canChangeMode: %d canChagedata: %d canChangePower:%d",
+                currentPortStatus[i].canChangeMode,
+                currentPortStatus[i].canChangeDataRole,
+                currentPortStatus[i].canChangePowerRole);
+
+            if (getPortModeHelper(names[i], currentPortStatus[i].supportedModes)
+                  != Status::SUCCESS) {
+                ALOGE("Error while retrieving port modes");
+                goto done;
+            }
+        }
+        return Status::SUCCESS;
+    }
+done:
+    return Status::ERROR;
+}
+
+Return<void> Usb::queryPortStatus() {
+    hidl_vec<PortStatus> currentPortStatus;
+    Status status;
+
+    status = getPortStatusHelper(currentPortStatus);
+    Return<void> ret = mCallback->notifyPortStatusChange(currentPortStatus,
+       status);
+    if (!ret.isOk())
+        ALOGE("queryPortStatus error %s", ret.description().c_str());
+
+    return Void();
+}
+struct data {
+    int uevent_fd;
+    android::hardware::usb::V1_0::implementation::Usb *usb;
+};
+
+static void uevent_event(uint32_t /*epevents*/, struct data *payload) {
+    char msg[UEVENT_MSG_LEN + 2];
+    char *cp;
+    int n;
+
+    n = uevent_kernel_multicast_recv(payload->uevent_fd, msg, UEVENT_MSG_LEN);
+    if (n <= 0)
+        return;
+    if (n >= UEVENT_MSG_LEN)   /* overflow -- discard */
+        return;
+
+    msg[n] = '\0';
+    msg[n + 1] = '\0';
+    cp = msg;
+
+    while (*cp) {
+        if (!strcmp(cp, "SUBSYSTEM=dual_role_usb")) {
+            ALOGE("uevent received %s", cp);
+            if (payload->usb->mCallback != NULL) {
+                hidl_vec<PortStatus> currentPortStatus;
+                Status status = getPortStatusHelper(currentPortStatus);
+                Return<void> ret =
+                    payload->usb->mCallback->notifyPortStatusChange(currentPortStatus, status);
+                if (!ret.isOk())
+                    ALOGE("error %s", ret.description().c_str());
+            }
+            break;
+        }
+        /* advance to after the next \0 */
+        while (*cp++);
+    }
+}
+
+void* work(void* param) {
+    int epoll_fd, uevent_fd;
+    struct epoll_event ev;
+    int nevents = 0;
+    struct data payload;
+
+    ALOGE("creating thread");
+
+    uevent_fd = uevent_open_socket(64*1024, true);
+
+    if (uevent_fd < 0) {
+        ALOGE("uevent_init: uevent_open_socket failed\n");
+        return NULL;
+    }
+
+    payload.uevent_fd = uevent_fd;
+    payload.usb = (android::hardware::usb::V1_0::implementation::Usb *)param;
+
+    fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+
+    ev.events = EPOLLIN;
+    ev.data.ptr = (void *)uevent_event;
+
+    epoll_fd = epoll_create(64);
+    if (epoll_fd == -1) {
+        ALOGE("epoll_create failed; errno=%d", errno);
+        goto error;
+    }
+
+    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, uevent_fd, &ev) == -1) {
+        ALOGE("epoll_ctl failed; errno=%d", errno);
+        goto error;
+    }
+
+    while (1) {
+        struct epoll_event events[64];
+
+        nevents = epoll_wait(epoll_fd, events, 64, -1);
+        if (nevents == -1) {
+            if (errno == EINTR)
+                continue;
+            ALOGE("usb epoll_wait failed; errno=%d", errno);
+            break;
+        }
+
+        for (int n = 0; n < nevents; ++n) {
+            if (events[n].data.ptr)
+                (*(void (*)(int, struct data *payload))events[n].data.ptr)
+                    (events[n].events, &payload);
+        }
+    }
+
+error:
+    close(uevent_fd);
+
+    if (epoll_fd >= 0)
+        close(epoll_fd);
+
+    return NULL;
+}
+
+
+Return<void> Usb::setCallback(const sp<IUsbCallback>& callback) {
+
+    if (mCallback != NULL) {
+        ALOGE("Callback already registered");
+        return Void();
+    }
+
+    mCallback = callback;
+    ALOGI("registering callback");
+
+    if (pthread_create(&mPoll, NULL, work, this)) {
+        ALOGE("pthread creation failed %d", errno);
+        mCallback = NULL;
+        return Void();
+    }
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace usb
+}  // namespace hardware
+}  // namespace android
diff --git a/usb/1.0/default/Usb.h b/usb/1.0/default/Usb.h
new file mode 100644
index 0000000..cf418f4
--- /dev/null
+++ b/usb/1.0/default/Usb.h
@@ -0,0 +1,50 @@
+#ifndef ANDROID_HARDWARE_USB_V1_0_USB_H
+#define ANDROID_HARDWARE_USB_V1_0_USB_H
+
+#include <android/hardware/usb/1.0/IUsb.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Log.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+
+#define LOG_TAG "android.hardware.usb@1.0-service"
+#define UEVENT_MSG_LEN 2048
+
+namespace android {
+namespace hardware {
+namespace usb {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::usb::V1_0::IUsb;
+using ::android::hardware::usb::V1_0::IUsbCallback;
+using ::android::hardware::usb::V1_0::PortRole;
+using ::android::hidl::base::V1_0::IBase;
+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;
+
+struct Usb : public IUsb {
+    Return<void> switchRole(const hidl_string& portName, const PortRole& role) override;
+    Return<void> setCallback(const sp<IUsbCallback>& callback) override;
+    Return<void> queryPortStatus() override;
+
+    sp<IUsbCallback> mCallback;
+    private:
+        pthread_t mPoll;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace usb
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_USB_V1_0_USB_H
diff --git a/usb/1.0/default/android.hardware.usb@1.0-service.rc b/usb/1.0/default/android.hardware.usb@1.0-service.rc
new file mode 100644
index 0000000..77dfc93
--- /dev/null
+++ b/usb/1.0/default/android.hardware.usb@1.0-service.rc
@@ -0,0 +1,4 @@
+service usb-hal-1-0 /system/bin/hw/android.hardware.usb@1.0-service
+    class hal
+    user system
+    group system
diff --git a/usb/1.0/default/service.cpp b/usb/1.0/default/service.cpp
new file mode 100644
index 0000000..b4db241
--- /dev/null
+++ b/usb/1.0/default/service.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+#include <hidl/HidlTransportSupport.h>
+#include "Usb.h"
+
+using android::sp;
+
+// libhwbinder:
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files
+using android::hardware::usb::V1_0::IUsb;
+using android::hardware::usb::V1_0::implementation::Usb;
+
+int main() {
+    const char instance[] = "usb_hal";
+
+    android::sp<IUsb> service = new Usb();
+
+    configureRpcThreadpool(1, true /*callerWillJoin*/);
+    service->registerAsService(instance);
+
+    ALOGI("USB HAL Ready.");
+    joinRpcThreadpool();
+}
diff --git a/usb/1.0/types.hal b/usb/1.0/types.hal
new file mode 100644
index 0000000..17cd8c7
--- /dev/null
+++ b/usb/1.0/types.hal
@@ -0,0 +1,214 @@
+/*
+ * 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.
+ */
+package android.hardware.usb@1.0;
+
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+
+    /*
+     * error value when the HAL operation fails for reasons not listed here.
+     */
+    ERROR = 1,
+
+    /*
+     * error value returned when input argument is invalid.
+     */
+    INVALID_ARGUMENT = 2,
+
+    /*
+     * error value returned when role string is unrecognized.
+     */
+    UNRECOGNIZED_ROLE = 3,
+};
+
+/*
+ * Denotes the Port role type.
+ * Passed as an argument for functions used to query or change port roles.
+ */
+enum PortRoleType : uint32_t {
+    /*
+     * Denotes the data role of the port.
+     * The port can either be a "host" or a "device" for data.
+     * This maps to the PortDataRole enum.
+     */
+    DATA_ROLE = 0,
+
+    /*
+     * Denotes the power role of the port.
+     * The port can either be a "source" or "sink" for power.
+     * This maps to PortPowerRole enum.
+     */
+    POWER_ROLE = 1,
+
+    /*
+     * USB ports can be a pure DFP port which can only act
+     * as a host. A UFP port which can only act as a device.
+     * Or a dual role ports which can either can as a host or
+     * a device. This property is used to mention them.
+     */
+    MODE = 2,
+};
+
+@export
+enum PortDataRole : uint32_t {
+    /*
+     * Indicates that the port does not have a data role.
+     * In case of DRP, the current data role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+
+    /*
+     * Indicates that the port is acting as a host for data.
+     */
+    HOST = 1,
+
+    /*
+     * Indicated that the port is acting as a device for data.
+     */
+    DEVICE = 2,
+
+    NUM_DATA_ROLES = 3,
+};
+
+@export
+enum PortPowerRole : uint32_t {
+    /*
+     * Indicates that the port does not have a power role.
+     * In case of DRP, the current power role of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+
+    /*
+     * Indicates that the port is supplying power to the other port.
+     */
+    SOURCE = 1,
+
+    /*
+     * Indicates that the port is sinking power from the other port.
+     */
+    SINK = 2,
+
+    NUM_POWER_ROLES = 3,
+};
+
+@export
+enum PortMode : uint32_t {
+    /*
+     * Indicates that the port does not have a mode.
+     * In case of DRP, the current mode of the port is only resolved
+     * when the type-c handshake happens.
+     */
+    NONE = 0,
+    /*
+     * Indicates that port can only act as device for data and sink for power.
+     */
+    UFP = 1,
+
+    /*
+     * Indicates the port can only act as host for data and source for power.
+     */
+    DFP = 2,
+
+    /*
+     * Indicates can either act as UFP or DFP at a given point of time.
+     */
+    DRP = 3,
+
+    NUM_MODES = 4,
+};
+
+/*
+ * Used as a container to send port role information.
+ */
+struct PortRole {
+    /*
+     * Indicates the type of Port Role.
+     * Maps to the PortRoleType enum.
+     */
+    PortRoleType type;
+
+    /*
+     * when type is HAL_USB_DATA_ROLE pass values from enum PortDataRole.
+     * when type is HAL_USB_POWER_ROLE pass values from enum PortPowerRole.
+     * when type is HAL_USB_MODE pass values from enum PortMode.
+     */
+    uint32_t role;
+};
+
+/*
+ * Used as the container to report data back to the caller.
+ * Represents the current connection status of a single USB port.
+ */
+struct PortStatus {
+     /*
+      * Name of the port.
+      * Used as the port's id by the caller.
+      */
+     string portName;
+
+     /*
+      * Data role of the port.
+      */
+     PortDataRole currentDataRole;
+
+     /*
+      * Power Role of thte port.
+      */
+     PortPowerRole currentPowerRole;
+
+     /*
+      * Mode in which the port is connected.
+      * Can be UFP or DFP.
+      */
+     PortMode currentMode;
+
+     /*
+      * True indicates that the port's mode can
+      * be changed. False otherwise.
+      */
+     bool canChangeMode;
+
+     /*
+      * True indicates that the port's data role
+      * can be changed. False otherwise.
+      * For example, true if Type-C PD PD_SWAP
+      * is supported.
+      */
+     bool canChangeDataRole;
+
+     /*
+      * True indicates that the port's power role
+      * can be changed. False otherwise.
+      * For example, true if Type-C PD PR_SWAP
+      * is supported.
+      */
+     bool canChangePowerRole;
+
+     /*
+      * Identifies the type of the local port.
+      *
+      * UFP - Indicates that port can only act as device for
+      *       data and sink for power.
+      * DFP - Indicates the port can only act as host for data
+      *       and source for power.
+      * DRP - Indicates can either act as UFP or DFP at a
+      *       given point of time.
+      */
+      PortMode supportedModes;
+};
diff --git a/usb/Android.bp b/usb/Android.bp
new file mode 100644
index 0000000..bbb3e4b
--- /dev/null
+++ b/usb/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+]
diff --git a/vehicle/2.0/Android.bp b/vehicle/2.0/Android.bp
new file mode 100644
index 0000000..986fb74
--- /dev/null
+++ b/vehicle/2.0/Android.bp
@@ -0,0 +1,216 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.vehicle@2.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0",
+    srcs: [
+        "types.hal",
+        "IVehicle.hal",
+        "IVehicleCallback.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/types.cpp",
+        "android/hardware/vehicle/2.0/VehicleAll.cpp",
+        "android/hardware/vehicle/2.0/VehicleCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle@2.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0",
+    srcs: [
+        "types.hal",
+        "IVehicle.hal",
+        "IVehicleCallback.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/types.h",
+        "android/hardware/vehicle/2.0/IVehicle.h",
+        "android/hardware/vehicle/2.0/IHwVehicle.h",
+        "android/hardware/vehicle/2.0/BnHwVehicle.h",
+        "android/hardware/vehicle/2.0/BpHwVehicle.h",
+        "android/hardware/vehicle/2.0/BsVehicle.h",
+        "android/hardware/vehicle/2.0/IVehicleCallback.h",
+        "android/hardware/vehicle/2.0/IHwVehicleCallback.h",
+        "android/hardware/vehicle/2.0/BnHwVehicleCallback.h",
+        "android/hardware/vehicle/2.0/BpHwVehicleCallback.h",
+        "android/hardware/vehicle/2.0/BsVehicleCallback.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vehicle@2.0",
+    generated_sources: ["android.hardware.vehicle@2.0_genc++"],
+    generated_headers: ["android.hardware.vehicle@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vehicle@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle.vts.driver@2.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "types.hal",
+        "IVehicle.hal",
+        "IVehicleCallback.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/types.vts.cpp",
+        "android/hardware/vehicle/2.0/Vehicle.vts.cpp",
+        "android/hardware/vehicle/2.0/VehicleCallback.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle.vts.driver@2.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "types.hal",
+        "IVehicle.hal",
+        "IVehicleCallback.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/types.vts.h",
+        "android/hardware/vehicle/2.0/Vehicle.vts.h",
+        "android/hardware/vehicle/2.0/VehicleCallback.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vehicle.vts.driver@2.0",
+    generated_sources: ["android.hardware.vehicle.vts.driver@2.0_genc++"],
+    generated_headers: ["android.hardware.vehicle.vts.driver@2.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vehicle.vts.driver@2.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vehicle@2.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle@2.0-IVehicle-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "IVehicle.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/Vehicle.vts.cpp",
+        "android/hardware/vehicle/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle@2.0-IVehicle-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "IVehicle.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/Vehicle.vts.h",
+        "android/hardware/vehicle/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vehicle@2.0-IVehicle-vts.profiler",
+    generated_sources: ["android.hardware.vehicle@2.0-IVehicle-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.vehicle@2.0-IVehicle-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.vehicle@2.0-IVehicle-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vehicle@2.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "IVehicleCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/VehicleCallback.vts.cpp",
+        "android/hardware/vehicle/2.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vehicle@2.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/vehicle/2.0/ $(genDir)/android/hardware/vehicle/2.0/",
+    srcs: [
+        "IVehicleCallback.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vehicle/2.0/VehicleCallback.vts.h",
+        "android/hardware/vehicle/2.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler",
+    generated_sources: ["android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.vehicle@2.0-IVehicleCallback-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vehicle@2.0",
+    ],
+}
diff --git a/vehicle/2.0/Android.mk b/vehicle/2.0/Android.mk
new file mode 100644
index 0000000..9544960
--- /dev/null
+++ b/vehicle/2.0/Android.mk
@@ -0,0 +1,2254 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vehicle@2.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/Obd2FloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.Obd2FloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/Obd2IntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.Obd2IntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (StatusCode)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/StatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.StatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SubscribeFlags)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SubscribeFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SubscribeFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SubscribeOptions)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SubscribeOptions.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SubscribeOptions
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerBootupReason)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerBootupReason.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerBootupReason
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerSetState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerSetState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerSetState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateConfigFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateConfigFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateConfigFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateShutdownParam)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateShutdownParam.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateShutdownParam
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleArea)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleArea.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleArea
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaConfig)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaDoor)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaDoor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaDoor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaMirror)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaMirror.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaMirror
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaSeat)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaSeat.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaSeat
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaWindow)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaWindow.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaWindow
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaZone)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaZone.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaZone
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioContextFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioContextFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioContextFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioExtFocusFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioExtFocusFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioExtFocusFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusRequest)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusRequest.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusRequest
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioHwVariantConfigFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioHwVariantConfigFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioHwVariantConfigFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioRoutingPolicyIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioRoutingPolicyIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioRoutingPolicyIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioStream)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioStream.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioStream
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioStreamFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioStreamFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioStreamFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeCapabilityFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeCapabilityFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeCapabilityFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeLimitIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeLimitIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeLimitIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleDisplay)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleDisplay.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleDisplay
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleDrivingStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleDrivingStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleDrivingStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleGear)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleGear.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleGear
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleHvacFanDirection)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleHvacFanDirection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleHvacFanDirection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleHwKeyInputAction)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleHwKeyInputAction.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleHwKeyInputAction
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleIgnitionState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleIgnitionState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleIgnitionState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleInstrumentClusterType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleInstrumentClusterType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleInstrumentClusterType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropConfig)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropValue)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropValue.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropValue
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleProperty)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleProperty.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleProperty
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyAccess)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyAccess.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyAccess
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyChangeMode)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyChangeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyChangeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyGroup)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyGroup.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyGroup
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyOperation)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyOperation.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyOperation
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleRadioConstants)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleRadioConstants.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleRadioConstants
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleTurnSignal)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleTurnSignal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleTurnSignal
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleUnit)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleUnit.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleUnit
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVehicle.hal
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IVehicle.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::IVehicle
+
+$(GEN): $(LOCAL_PATH)/IVehicle.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVehicleCallback.hal
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IVehicleCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::IVehicleCallback
+
+$(GEN): $(LOCAL_PATH)/IVehicleCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vehicle@2.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (FuelType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/Obd2FloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.Obd2FloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/Obd2IntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.Obd2IntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (StatusCode)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/StatusCode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.StatusCode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SubscribeFlags)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SubscribeFlags.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SubscribeFlags
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (SubscribeOptions)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/SubscribeOptions.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.SubscribeOptions
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerBootupReason)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerBootupReason.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerBootupReason
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerSetState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerSetState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerSetState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateConfigFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateConfigFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateConfigFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleApPowerStateShutdownParam)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleApPowerStateShutdownParam.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleApPowerStateShutdownParam
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleArea)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleArea.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleArea
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaConfig)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaDoor)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaDoor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaDoor
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaMirror)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaMirror.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaMirror
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaSeat)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaSeat.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaSeat
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaWindow)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaWindow.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaWindow
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAreaZone)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAreaZone.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAreaZone
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioContextFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioContextFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioContextFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioExtFocusFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioExtFocusFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioExtFocusFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusRequest)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusRequest.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusRequest
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioFocusState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioFocusState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioFocusState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioHwVariantConfigFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioHwVariantConfigFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioHwVariantConfigFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioRoutingPolicyIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioRoutingPolicyIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioRoutingPolicyIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioStream)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioStream.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioStream
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioStreamFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioStreamFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioStreamFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeCapabilityFlag)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeCapabilityFlag.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeCapabilityFlag
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeLimitIndex)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeLimitIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeLimitIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleAudioVolumeState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleAudioVolumeState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleAudioVolumeState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleDisplay)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleDisplay.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleDisplay
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleDrivingStatus)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleDrivingStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleDrivingStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleGear)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleGear.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleGear
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleHvacFanDirection)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleHvacFanDirection.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleHvacFanDirection
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleHwKeyInputAction)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleHwKeyInputAction.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleHwKeyInputAction
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleIgnitionState)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleIgnitionState.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleIgnitionState
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleInstrumentClusterType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleInstrumentClusterType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleInstrumentClusterType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropConfig)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropValue)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropValue.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropValue
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleProperty)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleProperty.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleProperty
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyAccess)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyAccess.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyAccess
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyChangeMode)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyChangeMode.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyChangeMode
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyGroup)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyGroup.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyGroup
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyOperation)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyOperation.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyOperation
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehiclePropertyType)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehiclePropertyType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehiclePropertyType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleRadioConstants)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleRadioConstants.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleRadioConstants
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleTurnSignal)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleTurnSignal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleTurnSignal
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VehicleUnit)
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/VehicleUnit.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::types.VehicleUnit
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVehicle.hal
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IVehicle.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::IVehicle
+
+$(GEN): $(LOCAL_PATH)/IVehicle.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVehicleCallback.hal
+#
+GEN := $(intermediates)/android/hardware/vehicle/V2_0/IVehicleCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicleCallback.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vehicle@2.0::IVehicleCallback
+
+$(GEN): $(LOCAL_PATH)/IVehicleCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/vehicle/2.0/IVehicle.hal b/vehicle/2.0/IVehicle.hal
new file mode 100644
index 0000000..cab6ce0
--- /dev/null
+++ b/vehicle/2.0/IVehicle.hal
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vehicle@2.0;
+
+import IVehicleCallback;
+
+interface IVehicle {
+  /**
+   * Returns a list of all property configurations supported by this vehicle
+   * HAL.
+   */
+  getAllPropConfigs() generates (vec<VehiclePropConfig> propConfigs);
+
+  /*
+   * Returns a list of property configurations for given properties.
+   *
+   * If requested VehicleProperty wasn't found it must return
+   * StatusCode::INVALID_ARG, otherwise a list of vehicle property
+   * configurations with StatusCode::OK
+   */
+  getPropConfigs(vec<VehicleProperty> props)
+          generates (StatusCode status, vec<VehiclePropConfig> propConfigs);
+
+  /**
+   * Get a vehicle property value.
+   *
+   * For VehiclePropertyChangeMode::STATIC properties, this method must always
+   * return the same value always.
+   * For VehiclePropertyChangeMode::ON_CHANGE properties, it must return the
+   * latest available value.
+   *
+   * Some properties like AUDIO_VOLUME requires to pass additional data in
+   * GET request in VehiclePropValue object.
+   *
+   * If there is no data available yet, which can happen during initial stage,
+   * this call must return immediately with an error code of
+   * StatusCode::TRY_AGAIN.
+   */
+  get(VehiclePropValue requestedPropValue)
+          generates (StatusCode status, VehiclePropValue propValue);
+
+  /**
+   * Set a vehicle property value.
+   *
+   * Timestamp of data must be ignored for set operation.
+   *
+   * Setting some properties require having initial state available. If initial
+   * data is not available yet this call must return StatusCode::TRY_AGAIN.
+   * For a property with separate power control this call must return
+   * StatusCode::NOT_AVAILABLE error if property is not powered on.
+   */
+  set(VehiclePropValue propValue) generates (StatusCode status);
+
+  /**
+   * Subscribes to property events.
+   *
+   * Clients must be able to subscribe to multiple properties at a time
+   * depending on data provided in options argument.
+   *
+   * @param listener This client must be called on appropriate event.
+   * @param options List of options to subscribe. SubscribeOption contains
+   *                information such as property Id, area Id, sample rate, etc.
+   */
+  subscribe(IVehicleCallback callback, vec<SubscribeOptions> options)
+          generates (StatusCode status);
+
+  /**
+   * Unsubscribes from property events.
+   *
+   * If this client wasn't subscribed to the given property, this method
+   * must return StatusCode::INVALID_ARG.
+   */
+  unsubscribe(IVehicleCallback callback, VehicleProperty propId)
+          generates (StatusCode status);
+
+  /**
+   * Print out debugging state for the vehicle hal.
+   *
+   * The text must be in ASCII encoding only.
+   *
+   * Performance requirements:
+   *
+   * The HAL must return from this call in less than 10ms. This call must avoid
+   * deadlocks, as it may be called at any point of operation. Any synchronization
+   * primitives used (such as mutex locks or semaphores) must be acquired
+   * with a timeout.
+   *
+   */
+  debugDump() generates (string s);
+};
diff --git a/vehicle/2.0/IVehicleCallback.hal b/vehicle/2.0/IVehicleCallback.hal
new file mode 100644
index 0000000..e7e05bf
--- /dev/null
+++ b/vehicle/2.0/IVehicleCallback.hal
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vehicle@2.0;
+
+interface IVehicleCallback {
+
+    /*
+     * Event callback happens whenever a variable that the API user has
+     * subscribed to needs to be reported. This may be based purely on
+     * threshold and frequency (a regular subscription, see subscribe call's
+     * arguments) or when the IVehicle#set method was called and the actual
+     * change needs to be reported.
+     *
+     * These callbacks are chunked.
+     *
+     * @param values that has been updated.
+     */
+    oneway onPropertyEvent(vec<VehiclePropValue> propValues);
+
+    /*
+     * This method gets called if the client was subscribed to a property using
+     * SubscribeFlags::SET_CALL flag and IVehicle#set(...) method was called.
+     *
+     * These events must be delivered to subscriber immediately without any
+     * batching.
+     *
+     * @param value Value that was set by a client.
+     */
+    oneway onPropertySet(VehiclePropValue propValue);
+
+    /*
+     * Set property value is usually asynchronous operation. Thus even if
+     * client received StatusCode::OK from the IVehicle::set(...) this
+     * doesn't guarantee that the value was successfully propagated to the
+     * vehicle network. If such rare event occurs this method must be called.
+     *
+     * @param errorCode - any value from StatusCode enum.
+     * @param property - a property where error has happened.
+     * @param areaId - bitmask that specifies in which areas the problem has
+     *                 occurred, must be 0 for global properties
+     */
+    oneway onPropertySetError(StatusCode errorCode,
+                              VehicleProperty propId,
+                              int32_t areaId);
+};
diff --git a/vehicle/2.0/default/Android.mk b/vehicle/2.0/default/Android.mk
new file mode 100644
index 0000000..4a27eeb
--- /dev/null
+++ b/vehicle/2.0/default/Android.mk
@@ -0,0 +1,118 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+module_prefix = android.hardware.vehicle@2.0
+
+###############################################################################
+# Vehicle reference implementation lib
+###############################################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(module_prefix)-manager-lib
+LOCAL_SRC_FILES := \
+    vehicle_hal_manager/AccessControlConfigParser.cpp \
+    vehicle_hal_manager/SubscriptionManager.cpp \
+    vehicle_hal_manager/VehicleHalManager.cpp \
+    vehicle_hal_manager/VehicleObjectPool.cpp \
+    vehicle_hal_manager/VehicleUtils.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    $(module_prefix) \
+
+include $(BUILD_STATIC_LIBRARY)
+
+###############################################################################
+# Vehicle default VehicleHAL implementation
+###############################################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= $(module_prefix)-default-impl-lib
+LOCAL_SRC_FILES:= \
+    impl/DefaultVehicleHal.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    $(module_prefix) \
+
+include $(BUILD_STATIC_LIBRARY)
+
+
+###############################################################################
+# Vehicle reference implementation unit tests
+###############################################################################
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= $(module_prefix)-manager-unit-tests
+
+LOCAL_WHOLE_STATIC_LIBRARIES := $(module_prefix)-manager-lib
+
+LOCAL_SRC_FILES:= \
+    tests/AccessControlConfigParser_test.cpp \
+    tests/SubscriptionManager_test.cpp \
+    tests/VehicleHalManager_test.cpp \
+    tests/VehicleObjectPool_test.cpp \
+    tests/VehiclePropConfigIndex_test.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    $(module_prefix) \
+
+LOCAL_CFLAGS += -Wall -Wextra
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_NATIVE_TEST)
+
+
+###############################################################################
+# Vehicle HAL service
+###############################################################################
+include $(CLEAR_VARS)
+LOCAL_MODULE := $(module_prefix)-service
+LOCAL_INIT_RC := $(module_prefix)-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+
+LOCAL_SRC_FILES := \
+    VehicleService.cpp
+
+LOCAL_WHOLE_STATIC_LIBRARIES := \
+    $(module_prefix)-manager-lib \
+    $(module_prefix)-default-impl-lib \
+
+LOCAL_SHARED_LIBRARIES := \
+    libbinder \
+    libhidlbase \
+    libhidltransport \
+    libhwbinder \
+    liblog \
+    libutils \
+    android.hardware.vehicle@2.0
+
+include $(BUILD_EXECUTABLE)
diff --git a/vehicle/2.0/default/VehicleHal.h b/vehicle/2.0/default/VehicleHal.h
new file mode 100644
index 0000000..2807f28
--- /dev/null
+++ b/vehicle/2.0/default/VehicleHal.h
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_VehicleHal_H_
+#define android_hardware_vehicle_V2_0_VehicleHal_H_
+
+#include <android/hardware/vehicle/2.0/IVehicle.h>
+#include "vehicle_hal_manager/VehicleObjectPool.h"
+
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+/**
+ * This is a low-level vehicle hal interface that should be implemented by
+ * Vendor.
+ */
+class VehicleHal {
+public:
+    using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
+
+    using HalEventFunction = std::function<void(VehiclePropValuePtr)>;
+    using HalErrorFunction = std::function<void(
+            StatusCode errorCode, VehicleProperty property, int32_t areaId)>;
+
+    virtual ~VehicleHal() {}
+
+    virtual std::vector<VehiclePropConfig> listProperties() = 0;
+    virtual VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+                                    StatusCode* outStatus) = 0;
+
+    virtual StatusCode set(const VehiclePropValue& propValue) = 0;
+
+    /**
+     * Subscribe to HAL property events. This method might be called multiple
+     * times for the same vehicle property to update subscribed areas or sample
+     * rate.
+     *
+     * @param property to subscribe
+     * @param areas a bitwise vehicle areas or 0 for all supported areas
+     * @param sampleRate sample rate in Hz for properties that support sample
+     *                   rate, e.g. for properties with
+     *                   VehiclePropertyChangeMode::CONTINUOUS
+     */
+    virtual StatusCode subscribe(VehicleProperty property,
+                               int32_t areas,
+                               float sampleRate) = 0;
+
+    /**
+     * Unsubscribe from HAL events for given property
+     *
+     * @param property vehicle property to unsubscribe
+     */
+    virtual StatusCode unsubscribe(VehicleProperty property) = 0;
+
+    /**
+     * Override this method if you need to do one-time initialization.
+     */
+    virtual void onCreate() {}
+
+    void init(
+        VehiclePropValuePool* valueObjectPool,
+        const HalEventFunction& onHalEvent,
+        const HalErrorFunction& onHalError) {
+        mValuePool = valueObjectPool;
+        mOnHalEvent = onHalEvent;
+        mOnHalPropertySetError = onHalError;
+
+        onCreate();
+    }
+
+    VehiclePropValuePool* getValuePool() {
+        return mValuePool;
+    }
+protected:
+    /* Propagates property change events to vehicle HAL clients. */
+    void doHalEvent(VehiclePropValuePtr v) {
+        mOnHalEvent(std::move(v));
+    }
+
+    /* Propagates error during set operation to the vehicle HAL clients. */
+    void doHalPropertySetError(StatusCode errorCode,
+                               VehicleProperty propId, int32_t areaId) {
+        mOnHalPropertySetError(errorCode, propId, areaId);
+    }
+
+private:
+    HalEventFunction mOnHalEvent;
+    HalErrorFunction mOnHalPropertySetError;
+    VehiclePropValuePool* mValuePool;
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif //android_hardware_vehicle_V2_0_VehicleHal_H_
diff --git a/vehicle/2.0/default/VehicleService.cpp b/vehicle/2.0/default/VehicleService.cpp
new file mode 100644
index 0000000..493df74
--- /dev/null
+++ b/vehicle/2.0/default/VehicleService.cpp
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-service"
+#include <android/log.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <iostream>
+
+
+#include <vehicle_hal_manager/VehicleHalManager.h>
+#include <impl/DefaultVehicleHal.h>
+
+using namespace android;
+using namespace android::hardware;
+using namespace android::hardware::vehicle::V2_0;
+
+int main(int /* argc */, char* /* argv */ []) {
+    auto hal = std::make_unique<impl::DefaultVehicleHal>();
+    auto service = std::make_unique<VehicleHalManager>(hal.get());
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+
+    ALOGI("Registering as service...");
+    service->registerAsService("Vehicle");
+
+    ALOGI("Ready");
+    joinRpcThreadpool();
+}
diff --git a/vehicle/2.0/default/android.hardware.vehicle@2.0-service.rc b/vehicle/2.0/default/android.hardware.vehicle@2.0-service.rc
new file mode 100644
index 0000000..622cb1e
--- /dev/null
+++ b/vehicle/2.0/default/android.hardware.vehicle@2.0-service.rc
@@ -0,0 +1,4 @@
+service vehicle-hal-2.0 /system/bin/hw/android.hardware.vehicle@2.0-service
+    class hal
+    user vehicle_network
+    group system
diff --git a/vehicle/2.0/default/impl/DefaultConfig.h b/vehicle/2.0/default/impl/DefaultConfig.h
new file mode 100644
index 0000000..12c1c1b
--- /dev/null
+++ b/vehicle/2.0/default/impl/DefaultConfig.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_impl_DefaultConfig_H_
+#define android_hardware_vehicle_V2_0_impl_DefaultConfig_H_
+
+#include <android/hardware/vehicle/2.0/IVehicle.h>
+#include <vehicle_hal_manager/VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+const VehiclePropConfig kVehicleProperties[] = {
+    {
+        .prop = VehicleProperty::INFO_MAKE,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::STATIC,
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_POWER_ON,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_DEFROSTER,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas =
+                VehicleAreaWindow::FRONT_WINDSHIELD
+                | VehicleAreaWindow::REAR_WINDSHIELD
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_RECIRC_ON,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_AC_ON,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_AUTO_ON,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1)
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_FAN_SPEED,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1),
+                .minInt32Value = 1,
+                .maxInt32Value = 7
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_FAN_DIRECTION,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_TEMPERATURE_SET,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas =
+                VehicleAreaZone::ROW_1_LEFT
+                | VehicleAreaZone::ROW_1_RIGHT,
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                .minFloatValue = 16,
+                .maxFloatValue = 32,
+            },
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                .minFloatValue = 16,
+                .maxFloatValue = 32,
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::NIGHT_MODE,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    },
+
+    {
+        .prop = VehicleProperty::DRIVING_STATUS,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    },
+
+    {
+        .prop = VehicleProperty::GEAR_SELECTION,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    },
+
+    {
+        .prop = VehicleProperty::INFO_FUEL_CAPACITY,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .minFloatValue = 0,
+                .maxFloatValue = 1.0
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::DISPLAY_BRIGHTNESS,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .minInt32Value = 0,
+                .maxInt32Value = 10
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::IGNITION_STATE,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    },
+
+    {
+        .prop = VehicleProperty::OBD2_LIVE_FRAME,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    },
+
+    {
+        .prop = VehicleProperty::OBD2_FREEZE_FRAME,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+    }
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_vehicle_V2_0_impl_DefaultConfig_H_
diff --git a/vehicle/2.0/default/impl/DefaultVehicleHal.cpp b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
new file mode 100644
index 0000000..4541168
--- /dev/null
+++ b/vehicle/2.0/default/impl/DefaultVehicleHal.cpp
@@ -0,0 +1,285 @@
+/*
+ * 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.
+ */
+
+#include "DefaultVehicleHal.h"
+
+#define LOG_TAG "default_vehicle"
+#include <android/log.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+VehicleHal::VehiclePropValuePtr DefaultVehicleHal::get(
+        const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    *outStatus = StatusCode::OK;
+
+    VehiclePropValuePtr v;
+    VehicleProperty property = requestedPropValue.prop;
+    int32_t areaId = requestedPropValue.areaId;
+    auto& pool = *getValuePool();
+
+    switch (property) {
+        case VehicleProperty::INFO_MAKE:
+            v = pool.obtainString("Default Car");
+            break;
+        case VehicleProperty::HVAC_FAN_SPEED:
+            v = pool.obtainInt32(mFanSpeed);
+            break;
+        case VehicleProperty::HVAC_POWER_ON:
+            v = pool.obtainBoolean(mHvacPowerOn);
+            break;
+        case VehicleProperty::HVAC_RECIRC_ON:
+            v = pool.obtainBoolean(mHvacRecircOn);
+            break;
+        case VehicleProperty::HVAC_AC_ON:
+            v = pool.obtainBoolean(mHvacAcOn);
+            break;
+        case VehicleProperty::HVAC_AUTO_ON:
+            v = pool.obtainBoolean(mHvacAutoOn);
+            break;
+        case VehicleProperty::HVAC_FAN_DIRECTION:
+            v = pool.obtainInt32(toInt(mFanDirection));
+            break;
+        case VehicleProperty::HVAC_DEFROSTER:
+            bool defroster;
+            *outStatus = getHvacDefroster(areaId, &defroster);
+            if (StatusCode::OK == *outStatus) {
+                v = pool.obtainBoolean(defroster);
+            }
+            break;
+        case VehicleProperty::HVAC_TEMPERATURE_SET:
+            float value;
+            *outStatus = getHvacTemperature(requestedPropValue.areaId,
+                                            &value);
+            if (StatusCode::OK == *outStatus) {
+                v = pool.obtainFloat(value);
+            }
+            break;
+        case VehicleProperty::INFO_FUEL_CAPACITY:
+            v = pool.obtainFloat(0.75f);
+            break;
+        case VehicleProperty::DISPLAY_BRIGHTNESS:
+            v = pool.obtainInt32(mBrightness);
+            break;
+        case VehicleProperty::NIGHT_MODE:
+            v = pool.obtainBoolean(false);
+            break;
+        case VehicleProperty::GEAR_SELECTION:
+            v = pool.obtainInt32(toInt(VehicleGear::GEAR_PARK));
+            break;
+        case VehicleProperty::DRIVING_STATUS:
+            v = pool.obtainInt32(toInt(VehicleDrivingStatus::UNRESTRICTED));
+            break;
+        case VehicleProperty::IGNITION_STATE:
+            v = pool.obtainInt32(toInt(VehicleIgnitionState::ACC));
+            break;
+        case VehicleProperty::OBD2_LIVE_FRAME:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2LiveFrame(&v);
+            break;
+        case VehicleProperty::OBD2_FREEZE_FRAME:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2FreezeFrame(&v);
+            break;
+        default:
+            *outStatus = StatusCode::INVALID_ARG;
+    }
+
+    if (StatusCode::OK == *outStatus && v.get() != nullptr) {
+        v->prop = property;
+        v->areaId = areaId;
+        v->timestamp = elapsedRealtimeNano();
+    }
+
+    return v;
+}
+
+StatusCode DefaultVehicleHal::set(const VehiclePropValue& propValue) {
+    auto property = propValue.prop;
+    const auto& v = propValue.value;
+
+    StatusCode status = StatusCode::OK;
+
+    switch (property) {
+        case VehicleProperty::HVAC_POWER_ON:
+            mHvacPowerOn = v.int32Values[0] == 1;
+            break;
+        case VehicleProperty::HVAC_RECIRC_ON:
+            mHvacRecircOn = v.int32Values[0] == 1;
+            break;
+        case VehicleProperty::HVAC_AC_ON:
+            mHvacAcOn = v.int32Values[0] == 1;
+            break;
+        case VehicleProperty::HVAC_AUTO_ON:
+            mHvacAutoOn = v.int32Values[0] == 1;
+            break;
+        case VehicleProperty::HVAC_DEFROSTER:
+            status = setHvacDefroster(propValue.areaId, v.int32Values[0] == 1);
+            break;
+        case VehicleProperty::HVAC_FAN_DIRECTION:
+            mFanDirection =
+                    static_cast<VehicleHvacFanDirection>(v.int32Values[0]);
+            break;
+        case VehicleProperty::HVAC_FAN_SPEED:
+            mFanSpeed = v.int32Values[0];
+            break;
+        case VehicleProperty::HVAC_TEMPERATURE_SET:
+            status = setHvacTemperature(propValue.areaId, v.floatValues[0]);
+            break;
+        case VehicleProperty::DISPLAY_BRIGHTNESS:
+            mBrightness = v.int32Values[0];
+            break;
+        default:
+            status = StatusCode::INVALID_ARG;
+    }
+
+    return status;
+}
+
+StatusCode DefaultVehicleHal::getHvacTemperature(int32_t areaId,
+                                                 float* outValue)  {
+    if (areaId == toInt(VehicleAreaZone::ROW_1_LEFT)) {
+        *outValue = mRow1LeftHvacTemperatureSet;
+    } else if (areaId == toInt(VehicleAreaZone::ROW_1_RIGHT)) {
+        *outValue = mRow1RightHvacTemperatureSet;
+    } else {
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::setHvacTemperature(
+    int32_t areaId, float value) {
+    if (areaId == toInt(VehicleAreaZone::ROW_1_LEFT)) {
+        mRow1LeftHvacTemperatureSet = value;
+    } else if (areaId == toInt(VehicleAreaZone::ROW_1_RIGHT)) {
+        mRow1RightHvacTemperatureSet = value;
+    } else {
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::getHvacDefroster(int32_t areaId,
+                                               bool* outValue) {
+    ALOGI("Getting Hvac defroster for area: 0x%x", areaId);
+
+    if (areaId == toInt(VehicleAreaWindow::FRONT_WINDSHIELD)) {
+        *outValue = mFrontDefroster;
+    } else if (areaId == toInt(VehicleAreaWindow::REAR_WINDSHIELD)) {
+        *outValue = mRearDefroster;
+    } else {
+        ALOGE("Unable to get hvac defroster for area: 0x%x", areaId);
+        return StatusCode::INVALID_ARG;
+    }
+
+    ALOGI("Getting Hvac defroster for area: 0x%x, OK", areaId);
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::setHvacDefroster(int32_t areaId, bool value) {
+    if (areaId == toInt(VehicleAreaWindow::FRONT_WINDSHIELD)) {
+        mFrontDefroster = value;
+    } else if (areaId == toInt(VehicleAreaWindow::REAR_WINDSHIELD)) {
+        mRearDefroster = value;
+    } else {
+        return StatusCode::INVALID_ARG;
+    }
+    return StatusCode::OK;
+}
+
+static std::vector<int32_t> fillObd2IntValues() {
+    std::vector<int32_t> intValues(toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX));
+#define SENSOR(name) toInt(Obd2IntegerSensorIndex:: name)
+    intValues[SENSOR(FUEL_SYSTEM_STATUS)] = toInt(FuelSystemStatus::CLOSED_LOOP);
+    intValues[SENSOR(MALFUNCTION_INDICATOR_LIGHT_ON)] = 0;
+    intValues[SENSOR(IGNITION_MONITORS_SUPPORTED)] = toInt(IgnitionMonitorKind::SPARK);
+    intValues[SENSOR(IGNITION_SPECIFIC_MONITORS)] =
+        CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+        CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+        SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+        SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE;
+    intValues[SENSOR(INTAKE_AIR_TEMPERATURE)] = 35;
+    intValues[SENSOR(COMMANDED_SECONDARY_AIR_STATUS)] =
+        toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF);
+    intValues[SENSOR(NUM_OXYGEN_SENSORS_PRESENT)] = 1;
+    intValues[SENSOR(RUNTIME_SINCE_ENGINE_START)] = 500;
+    intValues[SENSOR(DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON)] = 0;
+    intValues[SENSOR(WARMUPS_SINCE_CODES_CLEARED)] = 51;
+    intValues[SENSOR(DISTANCE_TRAVELED_SINCE_CODES_CLEARED)] = 365;
+    intValues[SENSOR(ABSOLUTE_BAROMETRIC_PRESSURE)] = 30;
+    intValues[SENSOR(CONTROL_MODULE_VOLTAGE)] = 12;
+    intValues[SENSOR(AMBIENT_AIR_TEMPERATURE)] = 18;
+    intValues[SENSOR(MAX_FUEL_AIR_EQUIVALENCE_RATIO)] = 1;
+    intValues[SENSOR(FUEL_TYPE)] = toInt(FuelType::GASOLINE);
+#undef SENSOR
+    return intValues;
+}
+
+static std::vector<float> fillObd2FloatValues() {
+    std::vector<float> floatValues(toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX));
+#define SENSOR(name) toInt(Obd2FloatSensorIndex:: name)
+    floatValues[SENSOR(CALCULATED_ENGINE_LOAD)] = 0.153;
+    floatValues[SENSOR(SHORT_TERM_FUEL_TRIM_BANK1)] = -0.16;
+    floatValues[SENSOR(LONG_TERM_FUEL_TRIM_BANK1)] = -0.16;
+    floatValues[SENSOR(SHORT_TERM_FUEL_TRIM_BANK2)] = -0.16;
+    floatValues[SENSOR(LONG_TERM_FUEL_TRIM_BANK2)] = -0.16;
+    floatValues[SENSOR(INTAKE_MANIFOLD_ABSOLUTE_PRESSURE)] = 7.5;
+    floatValues[SENSOR(ENGINE_RPM)] = 1250.;
+    floatValues[SENSOR(VEHICLE_SPEED)] = 40.;
+    floatValues[SENSOR(TIMING_ADVANCE)] = 2.5;
+    floatValues[SENSOR(THROTTLE_POSITION)] = 19.75;
+    floatValues[SENSOR(OXYGEN_SENSOR1_VOLTAGE)] = 0.265;
+    floatValues[SENSOR(FUEL_TANK_LEVEL_INPUT)] = 0.824;
+    floatValues[SENSOR(EVAPORATION_SYSTEM_VAPOR_PRESSURE)] = -0.373;
+    floatValues[SENSOR(CATALYST_TEMPERATURE_BANK1_SENSOR1)] = 190.;
+    floatValues[SENSOR(RELATIVE_THROTTLE_POSITION)] = 3.;
+    floatValues[SENSOR(ABSOLUTE_THROTTLE_POSITION_B)] = 0.306;
+    floatValues[SENSOR(ACCELERATOR_PEDAL_POSITION_D)] = 0.188;
+    floatValues[SENSOR(ACCELERATOR_PEDAL_POSITION_E)] = 0.094;
+    floatValues[SENSOR(COMMANDED_THROTTLE_ACTUATOR)] = 0.024;
+#undef SENSOR
+    return floatValues;
+}
+
+StatusCode DefaultVehicleHal::fillObd2LiveFrame(VehiclePropValuePtr* v) {
+    static std::vector<int32_t> intValues(fillObd2IntValues());
+    static std::vector<float> floatValues(fillObd2FloatValues());
+    (*v)->value.int32Values = intValues;
+    (*v)->value.floatValues = floatValues;
+    return StatusCode::OK;
+}
+
+StatusCode DefaultVehicleHal::fillObd2FreezeFrame(VehiclePropValuePtr* v) {
+    static std::vector<int32_t> intValues(fillObd2IntValues());
+    static std::vector<float> floatValues(fillObd2FloatValues());
+    (*v)->value.int32Values = intValues;
+    (*v)->value.floatValues = floatValues;
+    (*v)->value.stringValue = "P0010";
+    return StatusCode::OK;
+}
+
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/impl/DefaultVehicleHal.h b/vehicle/2.0/default/impl/DefaultVehicleHal.h
new file mode 100644
index 0000000..15a4789
--- /dev/null
+++ b/vehicle/2.0/default/impl/DefaultVehicleHal.h
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_impl_DefaultVehicleHal_H_
+#define android_hardware_vehicle_V2_0_impl_DefaultVehicleHal_H_
+
+#include <VehicleHal.h>
+#include <impl/DefaultConfig.h>
+#include <utils/SystemClock.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace impl {
+
+class DefaultVehicleHal : public VehicleHal {
+public:
+    std::vector<VehiclePropConfig> listProperties() override {
+        return std::vector<VehiclePropConfig>(std::begin(kVehicleProperties),
+                                              std::end(kVehicleProperties));
+    }
+
+    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+                            StatusCode* outStatus) override;
+
+    StatusCode set(const VehiclePropValue& propValue) override;
+
+    StatusCode subscribe(VehicleProperty property,
+                       int32_t areas,
+                       float sampleRate) {
+        // TODO(pavelm): implement
+        return StatusCode::OK;
+    }
+
+    StatusCode unsubscribe(VehicleProperty property) {
+        // TODO(pavelm): implement
+        return StatusCode::OK;
+    }
+
+private:
+    StatusCode getHvacTemperature(int32_t areaId, float* outValue);
+    StatusCode setHvacTemperature(int32_t areaId, float value);
+    StatusCode getHvacDefroster(int32_t areaId, bool* outValue);
+    StatusCode setHvacDefroster(int32_t areaId, bool value);
+    StatusCode fillObd2LiveFrame (VehiclePropValuePtr* v);
+    StatusCode fillObd2FreezeFrame (VehiclePropValuePtr* v);
+private:
+    int32_t mFanSpeed = 3;
+    int32_t mBrightness = 7;
+    float mRow1LeftHvacTemperatureSet = 16;
+    float mRow1RightHvacTemperatureSet = 22;
+    bool mFrontDefroster = false;
+    bool mRearDefroster = false;
+    bool mHvacPowerOn = true;
+    bool mHvacRecircOn = true;
+    bool mHvacAcOn = true;
+    bool mHvacAutoOn = true;
+    VehicleHvacFanDirection mFanDirection = VehicleHvacFanDirection::FACE;
+};
+
+}  // impl
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+
+#endif  // android_hardware_vehicle_V2_0_impl_DefaultVehicleHal_H_
diff --git a/vehicle/2.0/default/tests/AccessControlConfigParser_test.cpp b/vehicle/2.0/default/tests/AccessControlConfigParser_test.cpp
new file mode 100644
index 0000000..92d7e39
--- /dev/null
+++ b/vehicle/2.0/default/tests/AccessControlConfigParser_test.cpp
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <memory>
+#include <fstream>
+#include <unordered_set>
+
+#include "vehicle_hal_manager/AccessControlConfigParser.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+class AccessControlConfigParserTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        std::vector<VehicleProperty> supportedProperties {
+            VehicleProperty::HVAC_FAN_SPEED,
+            VehicleProperty::HVAC_FAN_DIRECTION,
+        };
+        parser.reset(new AccessControlConfigParser(supportedProperties));
+    }
+public:
+    PropertyAclMap aclMap;
+    std::unique_ptr<AccessControlConfigParser> parser;
+};
+
+TEST_F(AccessControlConfigParserTest, basicParsing) {
+    std::stringstream file;
+    file << "S:0x0500 1000 RW" << std::endl;
+
+    ASSERT_TRUE(parser->parseFromStream(&file, &aclMap));
+
+    ASSERT_EQ(1, aclMap.size());
+    auto it = aclMap.find(VehicleProperty::HVAC_FAN_SPEED);
+    ASSERT_NE(aclMap.end(), it);
+    ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
+    ASSERT_EQ(VehicleProperty::HVAC_FAN_SPEED, it->second.propId);
+    ASSERT_EQ(1000u, it->second.uid);
+}
+
+TEST_F(AccessControlConfigParserTest, multipleUids) {
+    std::stringstream file;
+    file << "Set AID_AUDIO 1004" << std::endl
+            << "Set AID_SYSTEM 1000" << std::endl
+            << "S:0x0500 AID_SYSTEM RW" << std::endl
+            << "S:0x0500 AID_AUDIO RW" << std::endl
+            << "S:0x0500 0xbeef R" << std::endl;  // Read-only.
+
+    std::unordered_set<unsigned> expectedUids {1000, 1004, 0xbeef};
+
+    ASSERT_TRUE(parser->parseFromStream(&file, &aclMap));
+
+    auto range = aclMap.equal_range(VehicleProperty::HVAC_FAN_SPEED);
+    for (auto it = range.first; it != range.second; ++it) {
+        auto& acl = it->second;
+
+        ASSERT_EQ(1, expectedUids.count(acl.uid))
+                << " uid: " << std::hex << acl.uid;
+
+        if (acl.uid == 0xbeef) {
+            ASSERT_EQ(VehiclePropertyAccess::READ, acl.access);
+        } else {
+            ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, acl.access);
+        }
+    }
+}
+
+TEST_F(AccessControlConfigParserTest, fileContainsJunk) {
+    std::stringstream file;
+    file << "This string will be ignored with warning in the log" << std::endl
+         << "# However comments are quit legitimate" << std::endl
+         << "S:0x0500 0xbeef R # YAY" << std::endl;
+
+    ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
+
+    ASSERT_EQ(1, aclMap.size());
+    auto it = aclMap.find(VehicleProperty::HVAC_FAN_SPEED);
+    ASSERT_NE(aclMap.end(), it);
+    ASSERT_EQ(VehiclePropertyAccess::READ, it->second.access);
+    ASSERT_EQ(VehicleProperty::HVAC_FAN_SPEED, it->second.propId);
+    ASSERT_EQ(0xbeef, it->second.uid);
+}
+
+TEST_F(AccessControlConfigParserTest, badIntegerFormat) {
+    std::stringstream file;
+    file << "S:0x0500 A12 RW " << std::endl;
+
+    ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
+    ASSERT_EQ(0, aclMap.size());
+}
+
+TEST_F(AccessControlConfigParserTest, ignoreNotSupportedProperties) {
+    std::stringstream file;
+    file << "S:0x0666 1000 RW " << std::endl;
+
+    ASSERT_FALSE(parser->parseFromStream(&file, &aclMap));
+    ASSERT_EQ(0, aclMap.size());
+}
+
+TEST_F(AccessControlConfigParserTest, multipleCalls) {
+    std::stringstream configFile;
+    configFile << "S:0x0500 1000 RW" << std::endl;
+
+    ASSERT_TRUE(parser->parseFromStream(&configFile, &aclMap));
+    ASSERT_EQ(1, aclMap.size());
+
+    std::stringstream configFile2;
+    configFile2 << "S:0x0501 1004 RW" << std::endl;
+    ASSERT_TRUE(parser->parseFromStream(&configFile2, &aclMap));
+    ASSERT_EQ(2, aclMap.size());
+
+    auto it = aclMap.find(VehicleProperty::HVAC_FAN_SPEED);
+    ASSERT_NE(aclMap.end(), it);
+    ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
+    ASSERT_EQ(VehicleProperty::HVAC_FAN_SPEED, it->second.propId);
+    ASSERT_EQ(1000u, it->second.uid);
+
+    it = aclMap.find(VehicleProperty::HVAC_FAN_DIRECTION);
+    ASSERT_NE(aclMap.end(), it);
+    ASSERT_EQ(VehiclePropertyAccess::READ_WRITE, it->second.access);
+    ASSERT_EQ(VehicleProperty::HVAC_FAN_DIRECTION, it->second.propId);
+    ASSERT_EQ(1004u, it->second.uid);
+}
+
+
+}  // namespace anonymous
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/tests/SubscriptionManager_test.cpp b/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
new file mode 100644
index 0000000..863142e
--- /dev/null
+++ b/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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.
+ */
+
+#include <unordered_map>
+#include <iostream>
+
+#include <gtest/gtest.h>
+
+#include "vehicle_hal_manager/SubscriptionManager.h"
+
+#include "VehicleHalTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+using namespace std::placeholders;
+
+class SubscriptionManagerTest : public ::testing::Test {
+public:
+    SubscriptionManager manager;
+
+    const VehicleProperty PROP1 = VehicleProperty::HVAC_FAN_SPEED;
+    const VehicleProperty PROP2 = VehicleProperty::DISPLAY_BRIGHTNESS;
+
+    sp<IVehicleCallback> cb1 = new MockedVehicleCallback();
+    sp<IVehicleCallback> cb2 = new MockedVehicleCallback();
+    sp<IVehicleCallback> cb3 = new MockedVehicleCallback();
+
+    hidl_vec<SubscribeOptions> subscrToProp1 = {
+        SubscribeOptions {
+            .propId = PROP1,
+            .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
+            .flags = SubscribeFlags::HAL_EVENT
+        },
+    };
+
+    hidl_vec<SubscribeOptions> subscrToProp2 = {
+        SubscribeOptions {
+            .propId = PROP2,
+            .flags = SubscribeFlags::HAL_EVENT
+        },
+    };
+
+    hidl_vec<SubscribeOptions> subscrToProp1and2 = {
+        SubscribeOptions {
+            .propId = PROP1,
+            .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
+            .flags = SubscribeFlags::HAL_EVENT
+        },
+        SubscribeOptions {
+            .propId = PROP2,
+            .flags = SubscribeFlags::HAL_EVENT
+        },
+    };
+
+    static std::list<sp<IVehicleCallback>> extractCallbacks(
+            const std::list<sp<HalClient>>& clients) {
+        std::list<sp<IVehicleCallback>> callbacks;
+        for (auto c : clients) {
+            callbacks.push_back(c->getCallback());
+        }
+        return callbacks;
+    }
+
+    std::list<sp<HalClient>> clientsToProp1() {
+        return manager.getSubscribedClients(PROP1,
+                                            toInt(VehicleAreaZone::ROW_1_LEFT),
+                                            SubscribeFlags::DEFAULT);
+    }
+
+    std::list<sp<HalClient>> clientsToProp2() {
+        return manager.getSubscribedClients(PROP2, 0,
+                                            SubscribeFlags::DEFAULT);
+    }
+};
+
+
+TEST_F(SubscriptionManagerTest, multipleClients) {
+    manager.addOrUpdateSubscription(cb1, subscrToProp1);
+    manager.addOrUpdateSubscription(cb2, subscrToProp1);
+
+    auto clients = manager.getSubscribedClients(
+            PROP1,
+            toInt(VehicleAreaZone::ROW_1_LEFT),
+            SubscribeFlags::HAL_EVENT);
+
+    ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
+}
+
+TEST_F(SubscriptionManagerTest, negativeCases) {
+    manager.addOrUpdateSubscription(cb1, subscrToProp1);
+
+    // Wrong zone
+    auto clients = manager.getSubscribedClients(
+            PROP1,
+            toInt(VehicleAreaZone::ROW_2_LEFT),
+            SubscribeFlags::HAL_EVENT);
+    ASSERT_TRUE(clients.empty());
+
+    // Wrong prop
+    clients = manager.getSubscribedClients(
+            VehicleProperty::AP_POWER_BOOTUP_REASON,
+            toInt(VehicleAreaZone::ROW_1_LEFT),
+            SubscribeFlags::HAL_EVENT);
+    ASSERT_TRUE(clients.empty());
+
+    // Wrong flag
+    clients = manager.getSubscribedClients(
+            PROP1,
+            toInt(VehicleAreaZone::ROW_1_LEFT),
+            SubscribeFlags::SET_CALL);
+    ASSERT_TRUE(clients.empty());
+}
+
+TEST_F(SubscriptionManagerTest, mulipleSubscriptions) {
+    manager.addOrUpdateSubscription(cb1, subscrToProp1);
+
+    auto clients = manager.getSubscribedClients(
+            PROP1,
+            toInt(VehicleAreaZone::ROW_1_LEFT),
+            SubscribeFlags::DEFAULT);
+    ASSERT_EQ((size_t) 1, clients.size());
+    ASSERT_EQ(cb1, clients.front()->getCallback());
+
+    // Same property, but different zone, to make sure we didn't unsubscribe
+    // from previous zone.
+    manager.addOrUpdateSubscription(cb1, {
+        SubscribeOptions {
+                .propId = PROP1,
+                .vehicleAreas = toInt(VehicleAreaZone::ROW_2),
+                .flags = SubscribeFlags::DEFAULT
+            }
+        });
+
+    clients = manager.getSubscribedClients(PROP1,
+                                           toInt(VehicleAreaZone::ROW_1_LEFT),
+                                           SubscribeFlags::DEFAULT);
+    ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
+
+    clients = manager.getSubscribedClients(PROP1,
+                                           toInt(VehicleAreaZone::ROW_2),
+                                           SubscribeFlags::DEFAULT);
+    ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
+}
+
+TEST_F(SubscriptionManagerTest, unsubscribe) {
+    manager.addOrUpdateSubscription(cb1, subscrToProp1);
+    manager.addOrUpdateSubscription(cb2, subscrToProp2);
+    manager.addOrUpdateSubscription(cb3, subscrToProp1and2);
+
+    ASSERT_ALL_EXISTS({cb1, cb3}, extractCallbacks(clientsToProp1()));
+    ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
+
+    ASSERT_FALSE(manager.unsubscribe(cb1, PROP1));
+    ASSERT_ALL_EXISTS({cb3}, extractCallbacks(clientsToProp1()));
+
+    // Make sure nothing changed in PROP2 so far.
+    ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
+
+    // No one subscribed to PROP1, subscription for PROP2 is not affected.
+    ASSERT_TRUE(manager.unsubscribe(cb3, PROP1));
+    ASSERT_ALL_EXISTS({cb2, cb3}, extractCallbacks(clientsToProp2()));
+
+    ASSERT_FALSE(manager.unsubscribe(cb3, PROP2));
+    ASSERT_ALL_EXISTS({cb2}, extractCallbacks(clientsToProp2()));
+
+    // The last client unsubscribed from this property.
+    ASSERT_TRUE(manager.unsubscribe(cb2, PROP2));
+
+    // No one was subscribed, return false.
+    ASSERT_FALSE(manager.unsubscribe(cb1, PROP1));
+}
+
+}  // namespace anonymous
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
new file mode 100644
index 0000000..4a20ea5
--- /dev/null
+++ b/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -0,0 +1,475 @@
+/*
+ * 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.
+ */
+
+#include <unordered_map>
+#include <iostream>
+
+#include <utils/SystemClock.h>
+
+#include <gtest/gtest.h>
+
+#include "vehicle_hal_manager/VehicleHalManager.h"
+
+#include "VehicleHalTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+using namespace std::placeholders;
+
+constexpr char kCarMake[] = "Default Car";
+constexpr int kRetriablePropMockedAttempts = 3;
+
+class MockedVehicleHal : public VehicleHal {
+public:
+    MockedVehicleHal() {
+        mConfigs.assign(std::begin(kVehicleProperties),
+                        std::end(kVehicleProperties));
+    }
+
+    std::vector<VehiclePropConfig> listProperties() override {
+        return mConfigs;
+    }
+
+    VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
+             StatusCode* outStatus) override {
+        *outStatus = StatusCode::OK;
+        VehiclePropValuePtr pValue;
+        VehicleProperty property = requestedPropValue.prop;
+        int32_t areaId = requestedPropValue.areaId;
+
+        switch (property) {
+            case VehicleProperty::INFO_MAKE:
+                pValue = getValuePool()->obtainString(kCarMake);
+                break;
+            case VehicleProperty::INFO_FUEL_CAPACITY:
+                if (fuelCapacityAttemptsLeft-- > 0) {
+                    // Emulate property not ready yet.
+                    *outStatus = StatusCode::TRY_AGAIN;
+                } else {
+                    pValue = getValuePool()->obtainFloat(42.42);
+                }
+                break;
+            case VehicleProperty::VEHICLE_MAPS_DATA_SERVICE:
+                pValue = getValuePool()->obtainComplex();
+                pValue->value.int32Values = hidl_vec<int32_t> { 10, 20 };
+                pValue->value.int64Values = hidl_vec<int64_t> { 30, 40 };
+                pValue->value.floatValues = hidl_vec<float_t> { 1.1, 2.2 };
+                pValue->value.bytes = hidl_vec<uint8_t> { 1, 2, 3 };
+                pValue->value.stringValue = kCarMake;
+                break;
+            default:
+                auto key = makeKey(property, areaId);
+                if (mValues.count(key) == 0) {
+                    ALOGW("");
+                }
+                pValue = getValuePool()->obtain(mValues[key]);
+        }
+
+        if (*outStatus == StatusCode::OK && pValue.get() != nullptr) {
+            pValue->prop = property;
+            pValue->areaId = areaId;
+            pValue->timestamp = elapsedRealtimeNano();
+        }
+
+        return pValue;
+    }
+
+    StatusCode set(const VehiclePropValue& propValue) override {
+        if (VehicleProperty::MIRROR_FOLD == propValue.prop
+                && mirrorFoldAttemptsLeft-- > 0) {
+            return StatusCode::TRY_AGAIN;
+        }
+
+        mValues[makeKey(propValue)] = propValue;
+        return StatusCode::OK;
+    }
+
+    StatusCode subscribe(VehicleProperty property,
+                       int32_t areas,
+                       float sampleRate) override {
+        return StatusCode::OK;
+    }
+
+    StatusCode unsubscribe(VehicleProperty property) override {
+        return StatusCode::OK;
+    }
+
+    void sendPropEvent(recyclable_ptr<VehiclePropValue> value) {
+        doHalEvent(std::move(value));
+    }
+
+    void sendHalError(StatusCode error, VehicleProperty property,
+                      int32_t areaId) {
+        doHalPropertySetError(error, property, areaId);
+    }
+
+public:
+    int fuelCapacityAttemptsLeft = kRetriablePropMockedAttempts;
+    int mirrorFoldAttemptsLeft = kRetriablePropMockedAttempts;
+
+private:
+    int64_t makeKey(const VehiclePropValue& v) const {
+        return makeKey(v.prop, v.areaId);
+    }
+
+    int64_t makeKey(VehicleProperty prop, int32_t area) const {
+        return (static_cast<int64_t>(prop) << 32) | area;
+    }
+
+private:
+    std::vector<VehiclePropConfig> mConfigs;
+    std::unordered_map<int64_t, VehiclePropValue> mValues;
+};
+
+class VehicleHalManagerTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        hal.reset(new MockedVehicleHal);
+        manager.reset(new VehicleHalManager(hal.get()));
+
+        objectPool = hal->getValuePool();
+    }
+
+    void TearDown() override {
+        manager.reset(nullptr);
+        hal.reset(nullptr);
+    }
+public:
+    void invokeGet(VehicleProperty property, int32_t areaId) {
+        VehiclePropValue requestedValue {};
+        requestedValue.prop = property;
+        requestedValue.areaId = areaId;
+
+        invokeGet(requestedValue);
+    }
+
+    void invokeGet(const VehiclePropValue& requestedPropValue) {
+        actualValue = VehiclePropValue {};  // reset previous values
+
+        StatusCode refStatus;
+        VehiclePropValue refValue;
+        bool called = false;
+        manager->get(requestedPropValue, [&refStatus, &refValue, &called]
+            (StatusCode status, const VehiclePropValue& value) {
+            refStatus = status;
+            refValue = value;
+            called = true;
+        });
+        ASSERT_TRUE(called) << "callback wasn't called for prop: "
+                            << enumToHexString(requestedPropValue.prop);
+
+        actualValue = refValue;
+        actualStatusCode = refStatus;
+    }
+
+public:
+    VehiclePropValue actualValue;
+    StatusCode actualStatusCode;
+
+    VehiclePropValuePool* objectPool;
+    std::unique_ptr<MockedVehicleHal> hal;
+    std::unique_ptr<VehicleHalManager> manager;
+};
+
+TEST_F(VehicleHalManagerTest, getPropConfigs) {
+    hidl_vec<VehicleProperty> properties =
+        { VehicleProperty::HVAC_FAN_SPEED, VehicleProperty::INFO_MAKE };
+    bool called = false;
+
+    manager->getPropConfigs(properties,
+            [&called] (StatusCode status,
+                       const hidl_vec<VehiclePropConfig>& c) {
+        ASSERT_EQ(StatusCode::OK, status);
+        ASSERT_EQ(2u, c.size());
+        called = true;
+    });
+
+    ASSERT_TRUE(called);  // Verify callback received.
+
+    called = false;
+    manager->getPropConfigs({ VehicleProperty::HVAC_FAN_SPEED },
+            [&called] (StatusCode status,
+                       const hidl_vec<VehiclePropConfig>& c) {
+        ASSERT_EQ(StatusCode::OK, status);
+        ASSERT_EQ(1u, c.size());
+        ASSERT_EQ(toString(kVehicleProperties[1]), toString(c[0]));
+        called = true;
+    });
+    ASSERT_TRUE(called);  // Verify callback received.
+
+    // TODO(pavelm): add case case when property was not declared.
+}
+
+TEST_F(VehicleHalManagerTest, getAllPropConfigs) {
+    bool called = false;
+    manager->getAllPropConfigs(
+            [&called] (const hidl_vec<VehiclePropConfig>& propConfigs) {
+        ASSERT_EQ(arraysize(kVehicleProperties), propConfigs.size());
+
+        for (size_t i = 0; i < propConfigs.size(); i++) {
+            ASSERT_EQ(toString(kVehicleProperties[i]),
+                      toString(propConfigs[i]));
+        }
+        called = true;
+    });
+    ASSERT_TRUE(called);  // Verify callback received.
+}
+
+TEST_F(VehicleHalManagerTest, halErrorEvent) {
+    const VehicleProperty PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
+
+    sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
+
+    hidl_vec<SubscribeOptions> options = {
+        SubscribeOptions {
+            .propId = PROP,
+            .flags = SubscribeFlags::DEFAULT
+        },
+    };
+
+    StatusCode res = manager->subscribe(cb, options);
+    ASSERT_EQ(StatusCode::OK, res);
+
+    hal->sendHalError(StatusCode::TRY_AGAIN, PROP, 0 /* area id*/);
+}
+
+TEST_F(VehicleHalManagerTest, subscribe) {
+    const VehicleProperty PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
+
+    sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
+
+    hidl_vec<SubscribeOptions> options = {
+        SubscribeOptions {
+            .propId = PROP,
+            .flags = SubscribeFlags::DEFAULT
+        }
+    };
+
+    StatusCode res = manager->subscribe(cb, options);
+    ASSERT_EQ(StatusCode::OK, res);
+
+    auto unsubscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
+    unsubscribedValue->prop = VehicleProperty::HVAC_FAN_SPEED;
+
+    hal->sendPropEvent(std::move(unsubscribedValue));
+    auto& receivedEnvents = cb->getReceivedEvents();
+
+    ASSERT_TRUE(cb->waitForExpectedEvents(0)) << " Unexpected events received: "
+                                              << receivedEnvents.size()
+                                              << (receivedEnvents.size() > 0
+                                                  ? toString(receivedEnvents.front()[0]) : "");
+
+    auto subscribedValue = objectPool->obtain(VehiclePropertyType::INT32);
+    subscribedValue->prop = PROP;
+    subscribedValue->value.int32Values[0] = 42;
+
+    cb->reset();
+    VehiclePropValue actualValue(*subscribedValue.get());
+    hal->sendPropEvent(std::move(subscribedValue));
+
+    ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
+                                              << receivedEnvents.size();
+
+    ASSERT_EQ(toString(actualValue),
+              toString(cb->getReceivedEvents().front()[0]));
+}
+
+TEST_F(VehicleHalManagerTest, subscribe_WriteOnly) {
+    const VehicleProperty PROP = VehicleProperty::HVAC_SEAT_TEMPERATURE;
+
+    sp<MockedVehicleCallback> cb = new MockedVehicleCallback();
+
+    hidl_vec<SubscribeOptions> options = {
+        SubscribeOptions {
+            .propId = PROP,
+            .flags = SubscribeFlags::HAL_EVENT
+        },
+    };
+
+    StatusCode res = manager->subscribe(cb, options);
+    // Unable to subscribe on Hal Events for write-only properties.
+    ASSERT_EQ(StatusCode::INVALID_ARG, res);
+
+
+    options[0].flags = SubscribeFlags::SET_CALL;
+
+    res = manager->subscribe(cb, options);
+    // OK to subscribe on SET method call for write-only properties.
+    ASSERT_EQ(StatusCode::OK, res);
+}
+
+TEST_F(VehicleHalManagerTest, get_Complex) {
+    invokeGet(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, 0);
+
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(VehicleProperty::VEHICLE_MAPS_DATA_SERVICE, actualValue.prop);
+
+    ASSERT_EQ(3, actualValue.value.bytes.size());
+    ASSERT_EQ(1, actualValue.value.bytes[0]);
+    ASSERT_EQ(2, actualValue.value.bytes[1]);
+    ASSERT_EQ(3, actualValue.value.bytes[2]);
+
+    ASSERT_EQ(2, actualValue.value.int32Values.size());
+    ASSERT_EQ(10, actualValue.value.int32Values[0]);
+    ASSERT_EQ(20, actualValue.value.int32Values[1]);
+
+    ASSERT_EQ(2, actualValue.value.floatValues.size());
+    ASSERT_FLOAT_EQ(1.1, actualValue.value.floatValues[0]);
+    ASSERT_FLOAT_EQ(2.2, actualValue.value.floatValues[1]);
+
+    ASSERT_EQ(2, actualValue.value.int64Values.size());
+    ASSERT_FLOAT_EQ(30, actualValue.value.int64Values[0]);
+    ASSERT_FLOAT_EQ(40, actualValue.value.int64Values[1]);
+
+    ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
+}
+
+TEST_F(VehicleHalManagerTest, get_StaticString) {
+    invokeGet(VehicleProperty::INFO_MAKE, 0);
+
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(VehicleProperty::INFO_MAKE, actualValue.prop);
+    ASSERT_STREQ(kCarMake, actualValue.value.stringValue.c_str());
+}
+
+TEST_F(VehicleHalManagerTest, get_NegativeCases) {
+    // Write-only property must fail.
+    invokeGet(VehicleProperty::HVAC_SEAT_TEMPERATURE, 0);
+    ASSERT_EQ(StatusCode::ACCESS_DENIED, actualStatusCode);
+
+    // Unknown property must fail.
+    invokeGet(VehicleProperty::MIRROR_Z_MOVE, 0);
+    ASSERT_EQ(StatusCode::INVALID_ARG, actualStatusCode);
+}
+
+TEST_F(VehicleHalManagerTest, get_Retriable) {
+    actualStatusCode = StatusCode::TRY_AGAIN;
+    int attempts = 0;
+    while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
+        invokeGet(VehicleProperty::INFO_FUEL_CAPACITY, 0);
+
+    }
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
+    ASSERT_FLOAT_EQ(42.42, actualValue.value.floatValues[0]);
+}
+
+TEST_F(VehicleHalManagerTest, set_Basic) {
+    const auto PROP = VehicleProperty::DISPLAY_BRIGHTNESS;
+    const auto VAL = 7;
+
+    auto expectedValue = hal->getValuePool()->obtainInt32(VAL);
+    expectedValue->prop = PROP;
+    expectedValue->areaId = 0;
+
+    actualStatusCode = manager->set(*expectedValue.get());
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+
+    invokeGet(PROP, 0);
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(PROP, actualValue.prop);
+    ASSERT_EQ(VAL, actualValue.value.int32Values[0]);
+}
+
+TEST_F(VehicleHalManagerTest, set_DifferentAreas) {
+    const auto PROP = VehicleProperty::HVAC_FAN_SPEED;
+    const auto VAL1 = 1;
+    const auto VAL2 = 2;
+    const auto AREA1 = toInt(VehicleAreaZone::ROW_1_LEFT);
+    const auto AREA2 = toInt(VehicleAreaZone::ROW_1_RIGHT);
+
+    {
+        auto expectedValue1 = hal->getValuePool()->obtainInt32(VAL1);
+        expectedValue1->prop = PROP;
+        expectedValue1->areaId = AREA1;
+        actualStatusCode = manager->set(*expectedValue1.get());
+        ASSERT_EQ(StatusCode::OK, actualStatusCode);
+
+        auto expectedValue2 = hal->getValuePool()->obtainInt32(VAL2);
+        expectedValue2->prop = PROP;
+        expectedValue2->areaId = AREA2;
+        actualStatusCode = manager->set(*expectedValue2.get());
+        ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    }
+
+    {
+        invokeGet(PROP, AREA1);
+        ASSERT_EQ(StatusCode::OK, actualStatusCode);
+        ASSERT_EQ(PROP, actualValue.prop);
+        ASSERT_EQ(AREA1, actualValue.areaId);
+        ASSERT_EQ(VAL1, actualValue.value.int32Values[0]);
+
+        invokeGet(PROP, AREA2);
+        ASSERT_EQ(StatusCode::OK, actualStatusCode);
+        ASSERT_EQ(PROP, actualValue.prop);
+        ASSERT_EQ(AREA2, actualValue.areaId);
+        ASSERT_EQ(VAL2, actualValue.value.int32Values[0]);
+    }
+}
+
+TEST_F(VehicleHalManagerTest, set_Retriable) {
+    const auto PROP = VehicleProperty::MIRROR_FOLD;
+
+    auto v = hal->getValuePool()->obtainBoolean(true);
+    v->prop = PROP;
+    v->areaId = 0;
+
+    actualStatusCode = StatusCode::TRY_AGAIN;
+    int attempts = 0;
+    while (StatusCode::TRY_AGAIN == actualStatusCode && ++attempts < 10) {
+        actualStatusCode = manager->set(*v.get());
+    }
+
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_EQ(kRetriablePropMockedAttempts + 1, attempts);
+
+    invokeGet(PROP, 0);
+    ASSERT_EQ(StatusCode::OK, actualStatusCode);
+    ASSERT_TRUE(actualValue.value.int32Values[0]);
+}
+
+TEST(HalClientVectorTest, basic) {
+    HalClientVector clients;
+    sp<IVehicleCallback> callback1 = new MockedVehicleCallback();
+
+    sp<HalClient> c1 = new HalClient(callback1, 10, 20);
+    sp<HalClient> c2 = new HalClient(callback1, 10, 20);
+
+    clients.addOrUpdate(c1);
+    clients.addOrUpdate(c1);
+    clients.addOrUpdate(c2);
+    ASSERT_EQ(2u, clients.size());
+    ASSERT_FALSE(clients.isEmpty());
+    ASSERT_LE(0, clients.indexOf(c1));
+    ASSERT_LE(0, clients.remove(c1));
+    ASSERT_GT(0, clients.indexOf(c1));  // c1 was already removed
+    ASSERT_GT(0, clients.remove(c1));   // attempt to remove c1 again
+    ASSERT_LE(0, clients.remove(c2));
+
+    ASSERT_TRUE(clients.isEmpty());
+}
+
+}  // namespace anonymous
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/vehicle/2.0/default/tests/VehicleHalTestUtils.h
new file mode 100644
index 0000000..b6a5c31
--- /dev/null
+++ b/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_VehicleDebugUtils_H_
+#define android_hardware_vehicle_V2_0_VehicleDebugUtils_H_
+
+#include <android/hardware/vehicle/2.0/types.h>
+#include <vehicle_hal_manager/VehicleUtils.h>
+#include <ios>
+#include <sstream>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+const VehiclePropConfig kVehicleProperties[] = {
+    {
+        .prop = VehicleProperty::INFO_MAKE,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::STATIC,
+        .configString = "Some=config,options=if,you=have_any",
+    },
+
+    {
+        .prop = VehicleProperty::HVAC_FAN_SPEED,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .supportedAreas = static_cast<int32_t>(
+            VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                .minInt32Value = 1,
+                .maxInt32Value = 7},
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                .minInt32Value = 1,
+                .maxInt32Value = 5,
+            }
+        }
+    },
+
+    // Write-only property
+    {
+        .prop = VehicleProperty::HVAC_SEAT_TEMPERATURE,
+        .access = VehiclePropertyAccess::WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_SET,
+        .supportedAreas = static_cast<int32_t>(
+            VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
+                .minInt32Value = 64,
+                .maxInt32Value = 80},
+            VehicleAreaConfig {
+                .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT),
+                .minInt32Value = 64,
+                .maxInt32Value = 80,
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::INFO_FUEL_CAPACITY,
+        .access = VehiclePropertyAccess::READ,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .minFloatValue = 0,
+                .maxFloatValue = 1.0
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::DISPLAY_BRIGHTNESS,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+        .areaConfigs = {
+            VehicleAreaConfig {
+                .minInt32Value = 0,
+                .maxInt32Value = 10
+            }
+        }
+    },
+
+    {
+        .prop = VehicleProperty::MIRROR_FOLD,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+
+    },
+
+    // Complex data type.
+    {
+        .prop = VehicleProperty::VEHICLE_MAPS_DATA_SERVICE,
+        .access = VehiclePropertyAccess::READ_WRITE,
+        .changeMode = VehiclePropertyChangeMode::ON_CHANGE
+    }
+};
+
+constexpr auto kTimeout = std::chrono::milliseconds(500);
+
+class MockedVehicleCallback : public IVehicleCallback {
+private:
+    using MuxGuard = std::lock_guard<std::mutex>;
+    using HidlVecOfValues = hidl_vec<VehiclePropValue>;
+public:
+    // Methods from ::android::hardware::vehicle::V2_0::IVehicleCallback follow.
+    Return<void> onPropertyEvent(
+            const hidl_vec<VehiclePropValue>& values) override {
+        {
+            MuxGuard  g(mLock);
+            mReceivedEvents.push_back(values);
+        }
+        mEventCond.notify_one();
+        return Return<void>();
+    }
+    Return<void> onPropertySet(const VehiclePropValue& value) override {
+        return Return<void>();
+    }
+    Return<void> onPropertySetError(StatusCode errorCode,
+                                    VehicleProperty propId,
+                                    int32_t areaId) override {
+        return Return<void>();
+    }
+
+    bool waitForExpectedEvents(size_t expectedEvents) {
+        std::unique_lock<std::mutex> g(mLock);
+
+        if (expectedEvents == 0 && mReceivedEvents.size() == 0) {
+            // No events expected, let's sleep a little bit to make sure
+            // nothing will show up.
+            return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout;
+        }
+
+        while (expectedEvents != mReceivedEvents.size()) {
+            if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    void reset() {
+        mReceivedEvents.clear();
+    }
+
+    const std::vector<HidlVecOfValues>& getReceivedEvents() {
+        return mReceivedEvents;
+    }
+
+private:
+    std::mutex mLock;
+    std::condition_variable mEventCond;
+    std::vector<HidlVecOfValues> mReceivedEvents;
+};
+
+template<typename T>
+inline std::string hexString(T value) {
+    std::stringstream ss;
+    ss << std::showbase << std::hex << value;
+    return ss.str();
+}
+
+template <typename T, typename Collection>
+inline void assertAllExistsAnyOrder(
+        std::initializer_list<T> expected,
+        const Collection& actual,
+        const char* msg) {
+    std::set<T> expectedSet = expected;
+
+    for (auto a: actual) {
+        ASSERT_EQ(1u, expectedSet.erase(a))
+                << msg << "\nContains not unexpected value.\n";
+    }
+
+    ASSERT_EQ(0u, expectedSet.size())
+            << msg
+            << "\nDoesn't contain expected value.";
+}
+
+#define ASSERT_ALL_EXISTS(...) \
+    assertAllExistsAnyOrder(__VA_ARGS__, (std::string("Called from: ") + \
+            std::string(__FILE__) + std::string(":") + \
+            std::to_string(__LINE__)).c_str()); \
+
+template<typename T>
+inline std::string enumToHexString(T value) {
+    return hexString(toInt(value));
+}
+
+template <typename T>
+inline std::string vecToString(const hidl_vec<T>& vec) {
+    std::stringstream ss("[");
+    for (size_t i = 0; i < vec.size(); i++) {
+        if (i != 0) ss << ",";
+        ss << vec[i];
+    }
+    ss << "]";
+    return ss.str();
+}
+
+inline std::string toString(const VehiclePropValue &v) {
+    std::stringstream ss;
+    ss << "VehiclePropValue {n"
+       << "  prop: " << enumToHexString(v.prop) << ",\n"
+       << "  areaId: " << hexString(v.areaId) << ",\n"
+       << "  timestamp: " << v.timestamp << ",\n"
+       << "  value {\n"
+       << "    int32Values: " << vecToString(v.value.int32Values) << ",\n"
+       << "    floatValues: " << vecToString(v.value.floatValues) << ",\n"
+       << "    int64Values: " << vecToString(v.value.int64Values) << ",\n"
+       << "    bytes: " << vecToString(v.value.bytes) << ",\n"
+       << "    string: " << v.value.stringValue.c_str() << ",\n"
+       << "  }\n"
+       << "}\n";
+
+    return ss.str();
+}
+
+inline std::string toString(const VehiclePropConfig &config) {
+    std::stringstream ss;
+    ss << "VehiclePropConfig {\n"
+       << "  prop: " << enumToHexString(config.prop) << ",\n"
+       << "  supportedAreas: " << hexString(config.supportedAreas) << ",\n"
+       << "  access: " << enumToHexString(config.access) << ",\n"
+       << "  changeMode: " << enumToHexString(config.changeMode) << ",\n"
+       << "  configFlags: " << hexString(config.configFlags) << ",\n"
+       << "  minSampleRate: " << config.minSampleRate << ",\n"
+       << "  maxSampleRate: " << config.maxSampleRate << ",\n"
+       << "  configString: " << config.configString.c_str() << ",\n";
+
+    ss << "  areaConfigs {\n";
+    for (size_t i = 0; i < config.areaConfigs.size(); i++) {
+        const auto &area = config.areaConfigs[i];
+        ss << "    areaId: " << hexString(area.areaId) << ",\n"
+           << "    minFloatValue: " << area.minFloatValue << ",\n"
+           << "    minFloatValue: " << area.maxFloatValue << ",\n"
+           << "    minInt32Value: " << area.minInt32Value << ",\n"
+           << "    minInt32Value: " << area.maxInt32Value << ",\n"
+           << "    minInt64Value: " << area.minInt64Value << ",\n"
+           << "    minInt64Value: " << area.maxInt64Value << ",\n";
+    }
+    ss << "  }\n"
+       << "}\n";
+
+    return ss.str();
+}
+
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+
+#endif //VEHICLEHALDEBUGUTILS_H
diff --git a/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp b/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
new file mode 100644
index 0000000..135f9fa
--- /dev/null
+++ b/vehicle/2.0/default/tests/VehicleObjectPool_test.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <utils/SystemClock.h>
+
+#include "vehicle_hal_manager/VehicleObjectPool.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+class VehicleObjectPoolTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        stats = PoolStats::instance();
+        resetStats();
+        valuePool.reset(new VehiclePropValuePool);
+    }
+
+    void TearDown() override {
+        // At the end, all created objects should be either recycled or deleted.
+        // Some objects could be recycled multiple times, that's why it's <=
+        ASSERT_EQ(stats->Obtained, stats->Recycled);
+        ASSERT_LE(stats->Created, stats->Recycled);
+    }
+private:
+    void resetStats() {
+        stats->Obtained = 0;
+        stats->Created = 0;
+        stats->Recycled = 0;
+    }
+
+public:
+    PoolStats* stats;
+    std::unique_ptr<VehiclePropValuePool> valuePool;
+};
+
+TEST_F(VehicleObjectPoolTest, valuePoolBasicCorrectness) {
+    void* raw = valuePool->obtain(VehiclePropertyType::INT32).get();
+    // At this point, v1 should be recycled and the only object in the pool.
+    ASSERT_EQ(raw, valuePool->obtain(VehiclePropertyType::INT32).get());
+    // Obtaining value of another type - should return a new object
+    ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::FLOAT).get());
+
+    ASSERT_EQ(3u, stats->Obtained);
+    ASSERT_EQ(2u, stats->Created);
+}
+
+TEST_F(VehicleObjectPoolTest, valuePoolStrings) {
+    valuePool->obtain(VehiclePropertyType::STRING);
+    auto vs = valuePool->obtain(VehiclePropertyType::STRING);
+    vs->value.stringValue = "Hello";
+    void* raw = vs.get();
+    vs.reset();  // delete the pointer
+
+    auto vs2 = valuePool->obtain(VehiclePropertyType::STRING);
+    ASSERT_EQ(0u, vs2->value.stringValue.size());
+    ASSERT_NE(raw, valuePool->obtain(VehiclePropertyType::STRING).get());
+
+    ASSERT_EQ(0u, stats->Obtained);
+}
+
+TEST_F(VehicleObjectPoolTest, valuePoolMultithreadedBenchmark) {
+    // In this test we have T threads that concurrently in C cycles
+    // obtain and release O VehiclePropValue objects of FLOAT / INT32 types.
+
+    const auto T = 2;
+    const auto C  = 500;
+    const auto O = 100;
+
+    auto poolPtr = valuePool.get();
+
+    std::vector<std::thread> threads;
+    auto start = elapsedRealtimeNano();
+    for (int i = 0; i < T; i++) {
+        threads.push_back(std::thread([&poolPtr] () {
+            for (int j = 0; j < C; j++) {
+                std::vector<recyclable_ptr<VehiclePropValue>> vec;
+                for (int k = 0; k < O; k++) {
+                    vec.push_back(
+                        poolPtr->obtain(k % 2 == 0
+                                        ? VehiclePropertyType::FLOAT
+                                        : VehiclePropertyType::INT32));
+                }
+            }
+        }));
+    }
+
+    for (auto& t : threads) {
+        t.join();
+    }
+    auto finish = elapsedRealtimeNano();
+
+    ASSERT_EQ(T * C * O, stats->Obtained);
+    ASSERT_EQ(T * C * O, stats->Recycled);
+    // Created less than obtained.
+    ASSERT_GE(T * O, stats->Created);
+
+    auto elapsedMs = (finish - start) / 1000000;
+    ASSERT_GE(1000, elapsedMs);  // Less a second to access 100K objects.
+                                 // Typically it takes about 0.1s on Nexus6P.
+}
+
+}  // namespace anonymous
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/tests/VehiclePropConfigIndex_test.cpp b/vehicle/2.0/default/tests/VehiclePropConfigIndex_test.cpp
new file mode 100644
index 0000000..28cdcbb
--- /dev/null
+++ b/vehicle/2.0/default/tests/VehiclePropConfigIndex_test.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+
+#include "vehicle_hal_manager/VehiclePropConfigIndex.h"
+
+#include "VehicleHalTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+namespace {
+
+class PropConfigTest : public ::testing::Test {
+protected:
+    void SetUp() override {
+        configs.assign(std::begin(kVehicleProperties),
+                       std::end(kVehicleProperties));
+    }
+
+    void TearDown() override {}
+
+public:
+    std::vector<VehiclePropConfig> configs;
+};
+
+TEST_F(PropConfigTest, hasConfig) {
+    VehiclePropConfigIndex index(configs);
+
+    ASSERT_TRUE(index.hasConfig(VehicleProperty::HVAC_FAN_SPEED));
+    ASSERT_TRUE(index.hasConfig(VehicleProperty::INFO_MAKE));
+    ASSERT_TRUE(index.hasConfig(VehicleProperty::INFO_FUEL_CAPACITY));
+
+    ASSERT_FALSE(index.hasConfig(VehicleProperty::INVALID));
+}
+
+TEST_F(PropConfigTest, getAllConfig) {
+    VehiclePropConfigIndex index(configs);
+
+    std::vector<VehiclePropConfig> actualConfigs = index.getAllConfigs();
+    ASSERT_EQ(configs.size(), actualConfigs.size());
+
+    for (size_t i = 0; i < actualConfigs.size(); i++) {
+        ASSERT_EQ(toString(configs[i]), toString(actualConfigs[i]));
+    }
+}
+
+TEST_F(PropConfigTest, getConfigs) {
+    VehiclePropConfigIndex index(configs);
+    auto actualConfig = index.getConfig(VehicleProperty::HVAC_FAN_SPEED);
+    ASSERT_EQ(toString(configs[1]), toString(actualConfig));
+}
+
+}  // namespace anonymous
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.cpp b/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.cpp
new file mode 100644
index 0000000..063a16d
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-impl"
+
+#include "AccessControlConfigParser.h"
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+AccessControlConfigParser::AccessControlConfigParser(
+        const std::vector<VehicleProperty>& properties) {
+    // Property Id in the config file doesn't include information about
+    // type and area. So we want to create a map from these kind of
+    // *stripped* properties to the whole VehicleProperty.
+    // We also want to filter out ACL to the properties that supported
+    // by concrete Vehicle HAL implementation.
+    for (VehicleProperty vehicleProperty : properties) {
+        auto numProp = static_cast<int>(vehicleProperty);
+        numProp &= ~static_cast<int>(VehiclePropertyType::MASK)
+                & ~static_cast<int>(VehicleArea::MASK);
+        mStrippedToVehiclePropertyMap.emplace(numProp, vehicleProperty);
+    }
+}
+
+bool AccessControlConfigParser::parseFromStream(
+        std::istream* stream, PropertyAclMap* propertyAclMap) {
+    std::list<std::string> tokens;
+    std::string line;
+    int lineNo = 0;
+    bool warnings = false;
+    for (;std::getline(*stream, line); lineNo++) {
+        split(line, &tokens);
+        if (!processTokens(&tokens, propertyAclMap)) {
+            warnings = true;
+            ALOGW("Failed to parse line %d : %s", lineNo, line.c_str());
+        }
+    }
+    return !warnings;
+}
+
+
+bool AccessControlConfigParser::processTokens(std::list<std::string>* tokens,
+                                              PropertyAclMap* propertyAclMap) {
+    std::string token = readNextToken(tokens);
+    if (token.empty() || token[0] == '#') {   // Ignore comment.
+        return true;
+    }
+
+    if (token == "Set") {
+        std::string alias = readNextToken(tokens);
+        std::string strUid = readNextToken(tokens);
+        if (alias.empty() || strUid.empty()) {
+            ALOGW("Expected alias and UID must be specified");
+            return false;
+        }
+        int uid;
+        if (!parseInt(strUid.c_str(), &uid)) {
+            ALOGW("Invalid UID: %d", uid);
+        }
+        mUidMap.emplace(std::move(alias), uid);
+    } else if (token.size() > 2 && token[1] == ':') {
+        VehiclePropertyGroup propGroup;
+        if (!parsePropertyGroup(token[0], &propGroup)) {
+            return false;
+        }
+        std::string strUid = readNextToken(tokens);
+        std::string strAccess = readNextToken(tokens);
+        if (strUid.empty() || strAccess.empty()) {
+            ALOGW("Expected UID and access for property: %s",
+                  token.c_str());
+        }
+
+
+        PropertyAcl acl;
+        if (parsePropertyId(token.substr(2), propGroup, &acl.propId)
+            && parseUid(strUid, &acl.uid)
+            && parseAccess(strAccess, &acl.access)) {
+            propertyAclMap->emplace(acl.propId, std::move(acl));
+        } else {
+            return false;
+        }
+    } else {
+        ALOGW("Unexpected token: %s", token.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool AccessControlConfigParser::parsePropertyGroup(
+        char group, VehiclePropertyGroup* outPropertyGroup) const {
+    switch (group) {
+        case 'S':  // Fall through.
+        case 's':
+            *outPropertyGroup = VehiclePropertyGroup::SYSTEM;
+            break;
+        case 'V':  // Fall through.
+        case 'v':
+            *outPropertyGroup = VehiclePropertyGroup::VENDOR;
+            break;
+        default:
+            ALOGW("Unexpected group: %c", group);
+            return false;
+    }
+    return true;
+}
+
+bool AccessControlConfigParser::parsePropertyId(
+        const std::string& strPropId,
+        VehiclePropertyGroup propertyGroup,
+        VehicleProperty* outVehicleProperty) const {
+    int propId;
+    if (!parseInt(strPropId.c_str(), &propId)) {
+        ALOGW("Failed to convert property id to integer: %s",
+              strPropId.c_str());
+        return false;
+    }
+    propId |= static_cast<int>(propertyGroup);
+    auto it = mStrippedToVehiclePropertyMap.find(propId);
+    if (it == mStrippedToVehiclePropertyMap.end()) {
+        ALOGW("Property Id not found or not supported: 0x%x", propId);
+        return false;
+    }
+    *outVehicleProperty = it->second;
+    return true;
+}
+
+bool AccessControlConfigParser::parseInt(const char* strValue,
+                                         int* outIntValue) {
+    char* end;
+    long num = std::strtol(strValue, &end, 0 /* auto detect base */);
+    bool success = *end == 0 && errno != ERANGE;
+    if (success) {
+        *outIntValue = static_cast<int>(num);
+    }
+
+    return success;
+}
+
+bool AccessControlConfigParser::parseUid(const std::string& strUid,
+                                         unsigned* outUid) const {
+    auto element = mUidMap.find(strUid);
+    if (element != mUidMap.end()) {
+        *outUid = element->second;
+    } else {
+        int val;
+        if (!parseInt(strUid.c_str(), &val)) {
+            ALOGW("Failed to convert UID '%s' to integer", strUid.c_str());
+            return false;
+        }
+        *outUid = static_cast<unsigned>(val);
+    }
+    return true;
+}
+
+bool AccessControlConfigParser::parseAccess(
+        const std::string& strAccess, VehiclePropertyAccess* outAccess) const {
+    if (strAccess.size() == 0 || strAccess.size() > 2) {
+        ALOGW("Unknown access mode '%s'", strAccess.c_str());
+        return false;
+    }
+    int32_t access = static_cast<int32_t>(VehiclePropertyAccess::NONE);
+    for (char c : strAccess) {
+        if (c == 'R' || c == 'r') {
+            access |= VehiclePropertyAccess::READ;
+        } else if (c == 'W' || c == 'w') {
+            access |= VehiclePropertyAccess::WRITE;
+        } else {
+            ALOGW("Unknown access mode: %c", c);
+            return false;
+        }
+    }
+    *outAccess = static_cast<VehiclePropertyAccess>(access);
+    return true;
+}
+
+void AccessControlConfigParser::split(const std::string& line,
+                                      std::list<std::string>* outTokens) {
+    outTokens->clear();
+    std::istringstream iss(line);
+
+    while (!iss.eof()) {
+        std::string token;
+        iss >> token;
+        outTokens->push_back(std::move(token));
+    }
+}
+
+std::string AccessControlConfigParser::readNextToken(
+        std::list<std::string>* tokens) const {
+    if (tokens->empty()) {
+        return "";
+    }
+
+    std::string token = tokens->front();
+    tokens->pop_front();
+    return token;
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.h b/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.h
new file mode 100644
index 0000000..5cd0c3e
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/AccessControlConfigParser.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_AccessControlConfigParser_H_
+#define android_hardware_vehicle_V2_0_AccessControlConfigParser_H_
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <list>
+
+#include <android/hardware/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+struct PropertyAcl {
+    VehicleProperty propId;
+    unsigned uid;
+    VehiclePropertyAccess access;
+};
+
+using PropertyAclMap = std::unordered_multimap<VehicleProperty, PropertyAcl>;
+
+/**
+ * Parser for per-property access control in vehicle HAL.
+ *
+ * It supports the following format:
+ *   Set ALIAS_NAME UID
+ *   {S,V}:0x0305   {ALIAS_NAME,UID}   {R,W,RW}
+ *
+ * ALIAS_NAME is just an alias for UID
+ * S - for system properties (VehiclePropertyGroup::SYSTEM)
+ * V - for vendor properties (VehiclePropertyGroup::VENDOR)
+ *
+ * Example:
+ *
+ *   Set AID_AUDIO  1004
+ *   Set AID_MY_APP     10022
+ *
+ *   S:0x0305   AID_AUDIO   RW
+ *   S:0x0305   10021       R
+ *   V:0x0101   AID_MY_APP  R
+ */
+class AccessControlConfigParser {
+public:
+    /**
+     * Creates an instance of AccessControlConfigParser
+     *
+     * @param properties - properties supported by HAL implementation
+     */
+    AccessControlConfigParser(const std::vector<VehicleProperty>& properties);
+
+    /**
+     * Parses config content from given stream and writes results to
+     * propertyAclMap.
+     */
+    bool parseFromStream(std::istream* stream, PropertyAclMap* propertyAclMap);
+
+private:
+    bool processTokens(std::list<std::string>* tokens,
+                       PropertyAclMap* propertyAclMap);
+
+    bool parsePropertyGroup(char group,
+                            VehiclePropertyGroup* outPropertyGroup) const;
+
+    bool parsePropertyId(const std::string& strPropId,
+                                VehiclePropertyGroup propertyGroup,
+                                VehicleProperty* outVehicleProperty) const;
+
+    bool parseUid(const std::string& strUid, unsigned* outUid) const;
+
+    bool parseAccess(const std::string& strAccess,
+                     VehiclePropertyAccess* outAccess) const;
+
+
+    std::string readNextToken(std::list<std::string>* tokens) const;
+
+    static bool parseInt(const char* strValue, int* outIntValue);
+    static void split(const std::string& line,
+                      std::list<std::string>* outTokens);
+
+private:
+    std::unordered_map<std::string, unsigned> mUidMap {};  // Contains UID
+    // aliases.
+
+    // Map property ids w/o TYPE and AREA to VehicleProperty.
+    std::unordered_map<int, VehicleProperty> mStrippedToVehiclePropertyMap;
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_vehicle_V2_0_AccessControlConfigParser_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/ConcurrentQueue.h b/vehicle/2.0/default/vehicle_hal_manager/ConcurrentQueue.h
new file mode 100644
index 0000000..8f575dc
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/ConcurrentQueue.h
@@ -0,0 +1,156 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_ConcurrentQueue_H_
+#define android_hardware_vehicle_V2_0_ConcurrentQueue_H_
+
+#include <queue>
+#include <atomic>
+#include <thread>
+#include <condition_variable>
+#include <iostream>
+
+namespace android {
+
+template<typename T>
+class ConcurrentQueue {
+public:
+    void waitForItems() {
+        std::unique_lock<std::mutex> g(mLock);
+        while (mQueue.empty() && mIsActive) {
+            mCond.wait(g);
+        }
+    }
+
+    std::vector<T> flush() {
+        std::vector<T> items;
+
+        MuxGuard g(mLock);
+        if (mQueue.empty() || !mIsActive) {
+            return items;
+        }
+        while (!mQueue.empty()) {
+            items.push_back(std::move(mQueue.front()));
+            mQueue.pop();
+        }
+        return items;
+    }
+
+    void push(T&& item) {
+        {
+            MuxGuard g(mLock);
+            if (!mIsActive) {
+                return;
+            }
+            mQueue.push(std::move(item));
+        }
+        mCond.notify_one();
+    }
+
+    /* Deactivates the queue, thus no one can push items to it, also
+     * notifies all waiting thread.
+     */
+    void deactivate() {
+        {
+            MuxGuard g(mLock);
+            mIsActive = false;
+        }
+        mCond.notify_all();  // To unblock all waiting consumers.
+    }
+
+    ConcurrentQueue() = default;
+
+    ConcurrentQueue(const ConcurrentQueue &) = delete;
+    ConcurrentQueue &operator=(const ConcurrentQueue &) = delete;
+private:
+    using MuxGuard = std::lock_guard<std::mutex>;
+
+    bool mIsActive = true;
+    mutable std::mutex mLock;
+    std::condition_variable mCond;
+    std::queue<T> mQueue;
+};
+
+template<typename T>
+class BatchingConsumer {
+private:
+    enum class State {
+        INIT = 0,
+        RUNNING = 1,
+        STOP_REQUESTED = 2,
+        STOPPED = 3,
+    };
+
+public:
+    BatchingConsumer() : mState(State::INIT) {}
+
+    BatchingConsumer(const BatchingConsumer &) = delete;
+    BatchingConsumer &operator=(const BatchingConsumer &) = delete;
+
+    using OnBatchReceivedFunc = std::function<void(const std::vector<T>& vec)>;
+
+    void run(ConcurrentQueue<T>* queue,
+             std::chrono::nanoseconds batchInterval,
+             const OnBatchReceivedFunc& func) {
+        mQueue = queue;
+        mBatchInterval = batchInterval;
+
+        mWorkerThread = std::thread(
+            &BatchingConsumer<T>::runInternal, this, func);
+    }
+
+    void requestStop() {
+        mState = State::STOP_REQUESTED;
+    }
+
+    void waitStopped() {
+        if (mWorkerThread.joinable()) {
+            mWorkerThread.join();
+        }
+    }
+
+private:
+    void runInternal(const OnBatchReceivedFunc& onBatchReceived) {
+        if (mState.exchange(State::RUNNING) == State::INIT) {
+            while (State::RUNNING == mState) {
+                mQueue->waitForItems();
+                if (State::STOP_REQUESTED == mState) break;
+
+                std::this_thread::sleep_for(mBatchInterval);
+                if (State::STOP_REQUESTED == mState) break;
+
+                std::vector<T> items = mQueue->flush();
+
+                if (items.size() > 0) {
+                    onBatchReceived(items);
+                }
+            }
+        }
+
+        mState = State::STOPPED;
+    }
+
+private:
+    std::thread mWorkerThread;
+
+    std::atomic<State> mState;
+    std::chrono::nanoseconds mBatchInterval;
+    ConcurrentQueue<T>* mQueue;
+};
+
+}  // namespace android
+
+#endif //android_hardware_vehicle_V2_0_ConcurrentQueue_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.cpp b/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.cpp
new file mode 100644
index 0000000..c190c71
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-impl"
+
+#include "SubscriptionManager.h"
+
+#include <cmath>
+
+#include <android/log.h>
+
+#include "VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+bool mergeSubscribeOptions(const SubscribeOptions &oldOpts,
+                           const SubscribeOptions &newOpts,
+                           SubscribeOptions *outResult) {
+
+    int32_t updatedAreas = oldOpts.vehicleAreas;
+    if (updatedAreas != kAllSupportedAreas) {
+        updatedAreas = newOpts.vehicleAreas != kAllSupportedAreas
+            ? updatedAreas | newOpts.vehicleAreas
+            : kAllSupportedAreas;
+    }
+
+    float updatedRate = std::max(oldOpts.sampleRate, newOpts.sampleRate);
+    SubscribeFlags updatedFlags = SubscribeFlags(oldOpts.flags | newOpts.flags);
+
+    bool updated = updatedRate > oldOpts.sampleRate
+                   || updatedAreas != oldOpts.vehicleAreas
+                   || updatedFlags != oldOpts.flags;
+    if (updated) {
+        *outResult = oldOpts;
+        outResult->vehicleAreas = updatedAreas;
+        outResult->sampleRate = updatedRate;
+        outResult->flags = updatedFlags;
+    }
+
+    return updated;
+}
+
+void HalClient::addOrUpdateSubscription(const SubscribeOptions &opts)  {
+    auto it = mSubscriptions.find(opts.propId);
+    if (it == mSubscriptions.end()) {
+        mSubscriptions.emplace(opts.propId, opts);
+    } else {
+        const SubscribeOptions& oldOpts = it->second;
+        SubscribeOptions updatedOptions;
+        if (mergeSubscribeOptions(oldOpts, opts, &updatedOptions)) {
+            mSubscriptions.erase(it);
+            mSubscriptions.emplace(opts.propId, updatedOptions);
+        }
+    }
+}
+
+bool HalClient::isSubscribed(VehicleProperty propId, int32_t areaId, SubscribeFlags flags) {
+    auto it = mSubscriptions.find(propId);
+    if (it == mSubscriptions.end()) {
+        return false;
+    }
+    const SubscribeOptions& opts = it->second;
+    bool res = (opts.flags & flags)
+           && (opts.vehicleAreas == 0 || areaId == 0 || opts.vehicleAreas & areaId);
+    return res;
+}
+
+std::list<SubscribeOptions> SubscriptionManager::addOrUpdateSubscription(
+        const sp<IVehicleCallback> &callback,
+        const hidl_vec<SubscribeOptions> &optionList) {
+    std::list<SubscribeOptions> updatedSubscriptions;
+
+    MuxGuard g(mLock);
+
+    const sp<HalClient>& client = getOrCreateHalClientLocked(callback);
+
+    for (size_t i = 0; i < optionList.size(); i++) {
+        const SubscribeOptions& opts = optionList[i];
+        client->addOrUpdateSubscription(opts);
+
+        addClientToPropMapLocked(opts.propId, client);
+
+        if (SubscribeFlags::HAL_EVENT & opts.flags) {
+            SubscribeOptions updated;
+            if (updateHalEventSubscriptionLocked(opts, &updated)) {
+                updatedSubscriptions.push_back(updated);
+            }
+        }
+    }
+
+    return updatedSubscriptions;
+}
+
+std::list<HalClientValues> SubscriptionManager::distributeValuesToClients(
+        const std::vector<recyclable_ptr<VehiclePropValue>>& propValues,
+        SubscribeFlags flags) const {
+    std::map<sp<HalClient>, std::list<VehiclePropValue*>> clientValuesMap;
+
+    {
+        MuxGuard g(mLock);
+        for (const auto& propValue: propValues) {
+            VehiclePropValue* v = propValue.get();
+            auto clients = getSubscribedClientsLocked(
+                v->prop, v->areaId, flags);
+            for (const auto& client : clients) {
+                clientValuesMap[client].push_back(v);
+            }
+        }
+    }
+
+    std::list<HalClientValues> clientValues;
+    for (const auto& entry : clientValuesMap) {
+        clientValues.push_back(HalClientValues {
+            .client = entry.first,
+            .values = entry.second
+        });
+    }
+
+    return clientValues;
+}
+
+std::list<sp<HalClient>> SubscriptionManager::getSubscribedClients(
+    VehicleProperty propId, int32_t area, SubscribeFlags flags) const {
+    MuxGuard g(mLock);
+    return getSubscribedClientsLocked(propId, area, flags);
+}
+
+std::list<sp<HalClient>> SubscriptionManager::getSubscribedClientsLocked(
+        VehicleProperty propId, int32_t area, SubscribeFlags flags) const {
+    std::list<sp<HalClient>> subscribedClients;
+
+    sp<HalClientVector> propClients = getClientsForPropertyLocked(propId);
+    if (propClients.get() != nullptr) {
+        for (size_t i = 0; i < propClients->size(); i++) {
+            const auto& client = propClients->itemAt(i);
+            if (client->isSubscribed(propId, area, flags)) {
+                subscribedClients.push_back(client);
+            }
+        }
+    }
+
+    return subscribedClients;
+}
+
+bool SubscriptionManager::updateHalEventSubscriptionLocked(
+        const SubscribeOptions &opts, SubscribeOptions *outUpdated) {
+    bool updated = false;
+    auto it = mHalEventSubscribeOptions.find(opts.propId);
+    if (it == mHalEventSubscribeOptions.end()) {
+        *outUpdated = opts;
+        mHalEventSubscribeOptions.emplace(opts.propId, opts);
+        updated = true;
+    } else {
+        const SubscribeOptions& oldOpts = it->second;
+
+        if (mergeSubscribeOptions(oldOpts, opts, outUpdated)) {
+            mHalEventSubscribeOptions.erase(opts.propId);
+            mHalEventSubscribeOptions.emplace(opts.propId, *outUpdated);
+            updated = true;
+        }
+    }
+
+    return updated;
+}
+
+void SubscriptionManager::addClientToPropMapLocked(
+        VehicleProperty propId, const sp<HalClient> &client) {
+    auto it = mPropToClients.find(propId);
+    sp<HalClientVector> propClients;
+    if (it == mPropToClients.end()) {
+        propClients = new HalClientVector();
+        mPropToClients.insert(std::make_pair(propId, propClients));
+    } else {
+        propClients = it->second;
+    }
+    propClients->addOrUpdate(client);
+}
+
+sp<HalClientVector> SubscriptionManager::getClientsForPropertyLocked(
+        VehicleProperty propId) const {
+    auto it = mPropToClients.find(propId);
+    return it == mPropToClients.end() ? nullptr : it->second;
+}
+
+sp<HalClient> SubscriptionManager::getOrCreateHalClientLocked(
+        const sp<IVehicleCallback>& callback) {
+    auto it = mClients.find(callback);
+    if (it == mClients.end()) {
+        IPCThreadState* self = IPCThreadState::self();
+        pid_t pid = self->getCallingPid();
+        uid_t uid = self->getCallingUid();
+        sp<HalClient> client = new HalClient(callback, pid, uid);
+        mClients.emplace(callback, client);
+        return client;
+    } else {
+        return it->second;
+    }
+}
+
+bool SubscriptionManager::unsubscribe(const sp<IVehicleCallback>& callback,
+                                      VehicleProperty propId) {
+    MuxGuard g(mLock);
+    auto propertyClients = getClientsForPropertyLocked(propId);
+    auto clientIter = mClients.find(callback);
+    if (clientIter == mClients.end()) {
+        ALOGW("Unable to unsubscribe: no callback found, propId: 0x%x", propId);
+    } else {
+        auto client = clientIter->second;
+
+        if (propertyClients != nullptr) {
+            propertyClients->remove(client);
+
+            if (propertyClients->isEmpty()) {
+                mPropToClients.erase(propId);
+            }
+        }
+
+        bool isClientSubscribedToOtherProps = false;
+        for (const auto& propClient : mPropToClients) {
+            if (propClient.second->indexOf(client) >= 0) {
+                isClientSubscribedToOtherProps = true;
+                break;
+            }
+        }
+
+        if (!isClientSubscribedToOtherProps) {
+            mClients.erase(clientIter);
+        }
+    }
+
+    return (propertyClients == nullptr || propertyClients->isEmpty())
+            ? mHalEventSubscribeOptions.erase(propId) == 1
+            : false;
+}
+
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.h b/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.h
new file mode 100644
index 0000000..9f2ed8d
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/SubscriptionManager.h
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_SubscriptionManager_H_
+#define android_hardware_vehicle_V2_0_SubscriptionManager_H_
+
+#include <memory>
+#include <map>
+#include <set>
+#include <list>
+
+#include <android/log.h>
+#include <hwbinder/IPCThreadState.h>
+
+#include <android/hardware/vehicle/2.0/IVehicle.h>
+
+#include "ConcurrentQueue.h"
+#include "VehicleObjectPool.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+class HalClient : public android::RefBase {
+public:
+    HalClient(const sp<IVehicleCallback> &callback,
+              int32_t pid,
+              int32_t uid)
+        : mCallback(callback), mPid(pid), mUid(uid) {}
+
+    virtual ~HalClient() {}
+public:
+    sp<IVehicleCallback> getCallback() const {
+        return mCallback;
+    }
+
+    void addOrUpdateSubscription(const SubscribeOptions &opts);
+
+    bool isSubscribed(VehicleProperty propId,
+                      int32_t areaId,
+                      SubscribeFlags flags);
+
+private:
+    const sp<IVehicleCallback> mCallback;
+    const int32_t mPid;
+    const int32_t mUid;
+
+    std::map<VehicleProperty, SubscribeOptions> mSubscriptions;
+};
+
+class HalClientVector : private SortedVector<sp<HalClient>> , public RefBase {
+public:
+    virtual ~HalClientVector() {}
+
+    inline void addOrUpdate(const sp<HalClient> &client) {
+        SortedVector::add(client);
+    }
+
+    using SortedVector::remove;
+    using SortedVector::size;
+    using SortedVector::indexOf;
+    using SortedVector::itemAt;
+    using SortedVector::isEmpty;
+};
+
+struct HalClientValues {
+    sp<HalClient> client;
+    std::list<VehiclePropValue *> values;
+};
+
+class SubscriptionManager {
+public:
+    virtual ~SubscriptionManager() {}
+
+    /**
+     * Updates subscription. Returns the vector of properties subscription that
+     * needs to be updated in VehicleHAL.
+     */
+    std::list<SubscribeOptions> addOrUpdateSubscription(
+            const sp<IVehicleCallback>& callback,
+            const hidl_vec<SubscribeOptions>& optionList);
+
+    /**
+     * Returns a list of IVehicleCallback -> list of VehiclePropValue ready for
+     * dispatching to its clients.
+     */
+    std::list<HalClientValues> distributeValuesToClients(
+            const std::vector<recyclable_ptr<VehiclePropValue>>& propValues,
+            SubscribeFlags flags) const;
+
+    std::list<sp<HalClient>> getSubscribedClients(
+        VehicleProperty propId, int32_t area, SubscribeFlags flags) const;
+
+    /**
+     * Returns true the client was unsubscribed successfully and there are
+     * no more clients subscribed to given propId.
+     */
+    bool unsubscribe(const sp<IVehicleCallback>& callback,
+                     VehicleProperty propId);
+private:
+    std::list<sp< HalClient>> getSubscribedClientsLocked(
+            VehicleProperty propId, int32_t area, SubscribeFlags flags) const;
+
+    bool updateHalEventSubscriptionLocked(const SubscribeOptions &opts,
+                                          SubscribeOptions *out);
+
+    void addClientToPropMapLocked(VehicleProperty propId,
+                                  const sp<HalClient> &client);
+
+    sp<HalClientVector> getClientsForPropertyLocked(
+            VehicleProperty propId) const;
+
+    sp<HalClient> getOrCreateHalClientLocked(
+            const sp<IVehicleCallback> &callback);
+
+private:
+    using MuxGuard = std::lock_guard<std::mutex>;
+
+    mutable std::mutex mLock;
+
+    std::map<sp<IVehicleCallback>, sp<HalClient>> mClients;
+    std::map<VehicleProperty, sp<HalClientVector>> mPropToClients;
+    std::map<VehicleProperty, SubscribeOptions> mHalEventSubscribeOptions;
+};
+
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+
+#endif // android_hardware_vehicle_V2_0_SubscriptionManager_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.cpp b/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.cpp
new file mode 100644
index 0000000..5d2e6fe
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.cpp
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-impl"
+
+#include "VehicleHalManager.h"
+
+#include <fstream>
+
+#include <android/log.h>
+#include <private/android_filesystem_config.h>
+
+#include "VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+using namespace std::placeholders;
+
+constexpr std::chrono::milliseconds kHalEventBatchingTimeWindow(10);
+
+const VehiclePropValue kEmptyValue{};
+
+/**
+ * Indicates what's the maximum size of hidl_vec<VehiclePropValue> we want
+ * to store in reusable object pool.
+ */
+constexpr auto kMaxHidlVecOfVehiclPropValuePoolSize = 20;
+
+Return<void> VehicleHalManager::getAllPropConfigs(
+        getAllPropConfigs_cb _hidl_cb) {
+    ALOGI("getAllPropConfigs called");
+    hidl_vec<VehiclePropConfig> hidlConfigs;
+    auto& halConfig = mConfigIndex->getAllConfigs();
+
+    hidlConfigs.setToExternal(
+            const_cast<VehiclePropConfig *>(halConfig.data()),
+            halConfig.size());
+
+    _hidl_cb(hidlConfigs);
+
+    return Void();
+}
+
+Return<void> VehicleHalManager::getPropConfigs(
+        const hidl_vec<VehicleProperty> &properties,
+        getPropConfigs_cb _hidl_cb) {
+    std::vector<VehiclePropConfig> configs;
+    for (size_t i = 0; i < properties.size(); i++) {
+        VehicleProperty prop = properties[i];
+        if (mConfigIndex->hasConfig(prop)) {
+            configs.push_back(mConfigIndex->getConfig(prop));
+        } else {
+            ALOGW("Requested config for undefined property: 0x%x", prop);
+            _hidl_cb(StatusCode::INVALID_ARG, hidl_vec<VehiclePropConfig>());
+        }
+    }
+
+    _hidl_cb(StatusCode::OK, configs);
+
+    return Void();
+}
+
+Return<void> VehicleHalManager::get(
+        const VehiclePropValue& requestedPropValue, get_cb _hidl_cb) {
+    const auto* config = getPropConfigOrNull(requestedPropValue.prop);
+    if (config == nullptr) {
+        ALOGE("Failed to get value: config not found, property: 0x%x",
+              requestedPropValue.prop);
+        _hidl_cb(StatusCode::INVALID_ARG, kEmptyValue);
+        return Void();
+    }
+
+    if (!checkReadPermission(*config, getCaller())) {
+        _hidl_cb(StatusCode::ACCESS_DENIED, kEmptyValue);
+        return Void();
+    }
+
+    StatusCode status;
+    auto value = mHal->get(requestedPropValue, &status);
+    _hidl_cb(status, value.get() ? *value : kEmptyValue);
+
+
+    return Void();
+}
+
+Return<StatusCode> VehicleHalManager::set(const VehiclePropValue &value) {
+    auto prop = value.prop;
+    const auto* config = getPropConfigOrNull(prop);
+    if (config == nullptr) {
+        ALOGE("Failed to set value: config not found, property: 0x%x", prop);
+        return StatusCode::INVALID_ARG;
+    }
+
+    if (!checkWritePermission(*config, getCaller())) {
+        return StatusCode::ACCESS_DENIED;
+    }
+
+    handlePropertySetEvent(value);
+
+    auto status = mHal->set(value);
+
+    return Return<StatusCode>(status);
+}
+
+Return<StatusCode> VehicleHalManager::subscribe(
+        const sp<IVehicleCallback> &callback,
+        const hidl_vec<SubscribeOptions> &options) {
+    hidl_vec<SubscribeOptions> verifiedOptions(options);
+    auto caller = getCaller();
+    for (size_t i = 0; i < verifiedOptions.size(); i++) {
+        SubscribeOptions& ops = verifiedOptions[i];
+        VehicleProperty prop = ops.propId;
+
+        const auto* config = getPropConfigOrNull(prop);
+        if (config == nullptr) {
+            ALOGE("Failed to subscribe: config not found, property: 0x%x",
+                  prop);
+            return StatusCode::INVALID_ARG;
+        }
+
+        if (!checkAcl(caller.uid, config->prop, VehiclePropertyAccess::READ)) {
+            return StatusCode::ACCESS_DENIED;
+        }
+
+        if (!isSubscribable(*config, ops.flags)) {
+            ALOGE("Failed to subscribe: property 0x%x is not subscribable",
+                  prop);
+            return StatusCode::INVALID_ARG;
+        }
+
+        int32_t areas = isGlobalProp(prop) ? 0 : ops.vehicleAreas;
+        if (areas != 0 && ((areas & config->supportedAreas) != areas)) {
+            ALOGE("Failed to subscribe property 0x%x. Requested areas 0x%x are "
+                  "out of supported range of 0x%x", prop, ops.vehicleAreas,
+                  config->supportedAreas);
+            return StatusCode::INVALID_ARG;
+        }
+
+        ops.vehicleAreas = areas;
+        ops.sampleRate = checkSampleRate(*config, ops.sampleRate);
+    }
+
+    std::list<SubscribeOptions> updatedOptions =
+        mSubscriptionManager.addOrUpdateSubscription(callback, verifiedOptions);
+
+    for (auto opt : updatedOptions) {
+        mHal->subscribe(opt.propId, opt.vehicleAreas, opt.sampleRate);
+    }
+    // TODO(pavelm): link to death callback (not implemented yet in HIDL)
+
+    return StatusCode::OK;
+}
+
+Return<StatusCode> VehicleHalManager::unsubscribe(
+        const sp<IVehicleCallback>& callback, VehicleProperty propId) {
+    if (mSubscriptionManager.unsubscribe(callback, propId)) {
+        mHal->unsubscribe(propId);
+    }
+    return StatusCode::OK;
+}
+
+Return<void> VehicleHalManager::debugDump(IVehicle::debugDump_cb _hidl_cb) {
+    _hidl_cb("");
+    return Void();
+}
+
+void VehicleHalManager::init() {
+    ALOGI("VehicleHalManager::init");
+
+    mHidlVecOfVehiclePropValuePool.resize(kMaxHidlVecOfVehiclPropValuePoolSize);
+
+
+    mBatchingConsumer.run(&mEventQueue,
+                          kHalEventBatchingTimeWindow,
+                          std::bind(&VehicleHalManager::onBatchHalEvent,
+                                    this, _1));
+
+    mHal->init(&mValueObjectPool,
+               std::bind(&VehicleHalManager::onHalEvent, this, _1),
+               std::bind(&VehicleHalManager::onHalPropertySetError, this,
+                         _1, _2, _3));
+
+    // Initialize index with vehicle configurations received from VehicleHal.
+    auto supportedPropConfigs = mHal->listProperties();
+    mConfigIndex.reset(new VehiclePropConfigIndex(supportedPropConfigs));
+
+    std::vector<VehicleProperty> supportedProperties(
+        supportedPropConfigs.size());
+    for (const auto& config : supportedPropConfigs) {
+        supportedProperties.push_back(config.prop);
+    }
+
+    AccessControlConfigParser aclParser(supportedProperties);
+    const char* configs[] = { "/system/etc/vehicle_access.conf",
+                              "/vendor/etc/vehicle_access.conf" };
+    for (const char* filename : configs) {
+        readAndParseAclConfig(filename, &aclParser, &mPropertyAclMap);
+    }
+}
+
+VehicleHalManager::~VehicleHalManager() {
+    mBatchingConsumer.requestStop();
+    mEventQueue.deactivate();
+    // We have to wait until consumer thread is fully stopped because it may
+    // be in a state of running callback (onBatchHalEvent).
+    mBatchingConsumer.waitStopped();
+    ALOGI("VehicleHalManager::dtor");
+}
+
+void VehicleHalManager::onHalEvent(VehiclePropValuePtr v) {
+    mEventQueue.push(std::move(v));
+}
+
+void VehicleHalManager::onHalPropertySetError(StatusCode errorCode,
+                                              VehicleProperty property,
+                                              int32_t areaId) {
+    const auto& clients = mSubscriptionManager.getSubscribedClients(
+            property, 0, SubscribeFlags::HAL_EVENT);
+
+    for (auto client : clients) {
+        client->getCallback()->onPropertySetError(errorCode, property, areaId);
+    }
+}
+
+void VehicleHalManager::onBatchHalEvent(
+        const std::vector<VehiclePropValuePtr>& values) {
+    const auto& clientValues = mSubscriptionManager.distributeValuesToClients(
+            values, SubscribeFlags::HAL_EVENT);
+
+    for (const HalClientValues& cv : clientValues) {
+        auto vecSize = cv.values.size();
+        hidl_vec<VehiclePropValue> vec;
+        if (vecSize < kMaxHidlVecOfVehiclPropValuePoolSize) {
+            vec.setToExternal(&mHidlVecOfVehiclePropValuePool[0], vecSize);
+        } else {
+            vec.resize(vecSize);
+        }
+
+        int i = 0;
+        for (VehiclePropValue* pValue : cv.values) {
+            shallowCopy(&(vec)[i++], *pValue);
+        }
+        cv.client->getCallback()->onPropertyEvent(vec);
+    }
+}
+
+bool VehicleHalManager::isSampleRateFixed(VehiclePropertyChangeMode mode) {
+    return (mode & VehiclePropertyChangeMode::ON_SET)
+           || (mode & VehiclePropertyChangeMode::ON_CHANGE);
+}
+
+float VehicleHalManager::checkSampleRate(const VehiclePropConfig &config,
+                                         float sampleRate) {
+    if (isSampleRateFixed(config.changeMode)) {
+        if (std::abs(sampleRate) > std::numeric_limits<float>::epsilon()) {
+            ALOGW("Sample rate is greater than zero for on change type. "
+                      "Ignoring it.");
+        }
+        return 0.0;
+    } else {
+        if (sampleRate > config.maxSampleRate) {
+            ALOGW("Sample rate %f is higher than max %f. Setting sampling rate "
+                      "to max.", sampleRate, config.maxSampleRate);
+            return config.maxSampleRate;
+        }
+        if (sampleRate < config.minSampleRate) {
+            ALOGW("Sample rate %f is lower than min %f. Setting sampling rate "
+                      "to min.", sampleRate, config.minSampleRate);
+            return config.minSampleRate;
+        }
+    }
+    return sampleRate;  // Provided sample rate was good, no changes.
+}
+
+bool VehicleHalManager::isSubscribable(const VehiclePropConfig& config,
+                                       SubscribeFlags flags) {
+    bool isReadable = config.access & VehiclePropertyAccess::READ;
+
+    if (!isReadable && (SubscribeFlags::HAL_EVENT & flags)) {
+        ALOGW("Cannot subscribe, property 0x%x is not readable", config.prop);
+        return false;
+    }
+    if (config.changeMode == VehiclePropertyChangeMode::STATIC) {
+        ALOGW("Cannot subscribe, property 0x%x is static", config.prop);
+        return false;
+    }
+
+    //TODO: extend to support event notification for set from android
+    if (config.changeMode == VehiclePropertyChangeMode::POLL) {
+        ALOGW("Cannot subscribe, property 0x%x is poll only", config.prop);
+        return false;
+    }
+    return true;
+}
+
+bool VehicleHalManager::checkAcl(uid_t callerUid, VehicleProperty propertyId,
+                                 VehiclePropertyAccess requiredAccess) const {
+    if (callerUid == AID_SYSTEM && isSystemProperty(propertyId)) {
+        return true;
+    }
+
+    auto range = mPropertyAclMap.equal_range(propertyId);
+    for (auto it = range.first; it != range.second; ++it) {
+        auto& acl = it->second;
+        if (acl.uid == callerUid && (acl.access & requiredAccess)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool VehicleHalManager::checkWritePermission(const VehiclePropConfig &config,
+                                             const Caller& caller) const {
+    if (!(config.access & VehiclePropertyAccess::WRITE)) {
+        ALOGW("Property 0%x has no write access", config.prop);
+        return false;
+    }
+    return checkAcl(caller.uid, config.prop, VehiclePropertyAccess::WRITE);
+}
+
+bool VehicleHalManager::checkReadPermission(const VehiclePropConfig &config,
+                                            const Caller& caller) const {
+    if (!(config.access & VehiclePropertyAccess::READ)) {
+        ALOGW("Property 0%x has no read access", config.prop);
+        return false;
+    }
+
+    return checkAcl(caller.uid, config.prop, VehiclePropertyAccess::READ);
+}
+
+void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
+    auto clients = mSubscriptionManager.getSubscribedClients(
+            value.prop, value.areaId, SubscribeFlags::SET_CALL);
+    for (auto client : clients) {
+        client->getCallback()->onPropertySet(value);
+    }
+}
+
+const VehiclePropConfig* VehicleHalManager::getPropConfigOrNull(
+        VehicleProperty prop) const {
+    return mConfigIndex->hasConfig(prop)
+           ? &mConfigIndex->getConfig(prop) : nullptr;
+}
+
+Caller VehicleHalManager::getCaller() {
+    Caller caller;
+    IPCThreadState* self = IPCThreadState::self();
+    caller.pid = self->getCallingPid();
+    caller.uid = self->getCallingUid();
+
+    return caller;
+}
+
+void VehicleHalManager::readAndParseAclConfig(const char* filename,
+                                              AccessControlConfigParser* parser,
+                                              PropertyAclMap* outAclMap) {
+    std::ifstream file(filename);
+    if (file.is_open()) {
+        ALOGI("Parsing file: %s", filename);
+        parser->parseFromStream(&file, outAclMap);
+        file.close();
+    }
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.h b/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.h
new file mode 100644
index 0000000..6768741
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleHalManager.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2015 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_vehicle_V2_0_VehicleHalManager_H_
+#define android_hardware_vehicle_V2_0_VehicleHalManager_H_
+
+#include <inttypes.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <list>
+#include <map>
+#include <memory>
+#include <set>
+
+#include <android/hardware/vehicle/2.0/IVehicle.h>
+#include <hwbinder/IPCThreadState.h>
+
+#include "AccessControlConfigParser.h"
+#include "ConcurrentQueue.h"
+#include "SubscriptionManager.h"
+#include "VehicleHal.h"
+#include "VehicleObjectPool.h"
+#include "VehiclePropConfigIndex.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+struct Caller {
+    pid_t pid;
+    uid_t uid;
+};
+
+/**
+ * This class is a thick proxy between IVehicle HIDL interface and vendor's implementation.
+ *
+ * It has some boilerplate code like batching and caching property values, checking permissions,
+ * etc. Vendors must implement VehicleHal class.
+ */
+class VehicleHalManager : public IVehicle {
+public:
+    VehicleHalManager(VehicleHal* vehicleHal)
+        : mHal(vehicleHal) {
+        init();
+    }
+
+    virtual ~VehicleHalManager();
+
+    void init();
+
+    // ---------------------------------------------------------------------------------------------
+    // Methods derived from IVehicle
+    Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb)  override;
+    Return<void> getPropConfigs(const hidl_vec<VehicleProperty>& properties,
+                                getPropConfigs_cb _hidl_cb)  override;
+    Return<void> get(const VehiclePropValue& requestedPropValue,
+                     get_cb _hidl_cb)  override;
+    Return<StatusCode> set(const VehiclePropValue& value)  override;
+    Return<StatusCode> subscribe(const sp<IVehicleCallback>& callback,
+                                const hidl_vec<SubscribeOptions>& options)  override;
+    Return<StatusCode> unsubscribe(const sp<IVehicleCallback>& callback,
+                                   VehicleProperty propId)  override;
+    Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override;
+
+private:
+    using VehiclePropValuePtr = VehicleHal::VehiclePropValuePtr;
+    // Returns true if needs to call again shortly.
+    using RetriableAction = std::function<bool()>;
+
+    // ---------------------------------------------------------------------------------------------
+    // Events received from VehicleHal
+    void onHalEvent(VehiclePropValuePtr  v);
+    void onHalPropertySetError(StatusCode errorCode, VehicleProperty property,
+                               int32_t areaId);
+
+    // ---------------------------------------------------------------------------------------------
+    // This method will be called from BatchingConsumer thread
+    void onBatchHalEvent(const std::vector<VehiclePropValuePtr >& values);
+
+    void handlePropertySetEvent(const VehiclePropValue& value);
+
+    const VehiclePropConfig* getPropConfigOrNull(VehicleProperty prop) const;
+
+    bool checkWritePermission(const VehiclePropConfig &config,
+                              const Caller& callee) const;
+    bool checkReadPermission(const VehiclePropConfig &config,
+                             const Caller& caller) const;
+    bool checkAcl(uid_t callerUid,
+                  VehicleProperty propertyId,
+                  VehiclePropertyAccess requiredAccess) const;
+
+    static bool isSubscribable(const VehiclePropConfig& config,
+                               SubscribeFlags flags);
+    static bool isSampleRateFixed(VehiclePropertyChangeMode mode);
+    static float checkSampleRate(const VehiclePropConfig& config,
+                                 float sampleRate);
+    static void readAndParseAclConfig(const char* filename,
+                                      AccessControlConfigParser* parser,
+                                      PropertyAclMap* outAclMap);
+
+    static Caller getCaller();
+
+private:
+    VehicleHal* mHal;
+    std::unique_ptr<VehiclePropConfigIndex> mConfigIndex;
+    SubscriptionManager mSubscriptionManager;
+
+    hidl_vec<VehiclePropValue> mHidlVecOfVehiclePropValuePool;
+
+    ConcurrentQueue<VehiclePropValuePtr> mEventQueue;
+    BatchingConsumer<VehiclePropValuePtr> mBatchingConsumer;
+    VehiclePropValuePool mValueObjectPool;
+    PropertyAclMap mPropertyAclMap;
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+
+#endif // android_hardware_vehicle_V2_0_VehicleHalManager_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp
new file mode 100644
index 0000000..e9dd68d
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-impl"
+
+#include "VehicleObjectPool.h"
+
+#include <log/log.h>
+
+#include "VehicleUtils.h"
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
+        VehiclePropertyType type, size_t vecSize) {
+    return isDisposable(type, vecSize)
+           ? obtainDisposable(type, vecSize)
+           : obtainRecylable(type, vecSize);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
+        const VehiclePropValue& src) {
+    if (src.prop == VehicleProperty::INVALID) {
+        ALOGE("Unable to obtain an object from pool for unknown property");
+        return RecyclableType();
+    }
+    VehiclePropertyType type = getPropType(src.prop);
+    size_t vecSize = getVehicleRawValueVectorSize(src.value, type);;
+    auto dest = obtain(type, vecSize);
+
+    dest->prop = src.prop;
+    dest->areaId = src.areaId;
+    dest->timestamp = src.timestamp;
+    copyVehicleRawValue(&dest->value, src.value);
+
+    return dest;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(
+        int32_t value) {
+    auto val = obtain(VehiclePropertyType::INT32);
+    val->value.int32Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(
+        int64_t value) {
+    auto val = obtain(VehiclePropertyType::INT64);
+    val->value.int64Values[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(
+        float value)  {
+    auto val = obtain(VehiclePropertyType::FLOAT);
+    val->value.floatValues[0] = value;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(
+        const char* cstr) {
+    auto val = obtain(VehiclePropertyType::STRING);
+    val->value.stringValue = cstr;
+    return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
+    return obtain(VehiclePropertyType::COMPLEX);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecylable(
+        VehiclePropertyType type, size_t vecSize) {
+    // VehiclePropertyType is not overlapping with vectorSize.
+    int32_t key = static_cast<int32_t>(type)
+                  | static_cast<int32_t>(vecSize);
+
+    std::lock_guard<std::mutex> g(mLock);
+    auto it = mValueTypePools.find(key);
+
+    if (it == mValueTypePools.end()) {
+        auto newPool(std::make_unique<InternalPool>(type, vecSize));
+        it = mValueTypePools.emplace(key, std::move(newPool)).first;
+    }
+    return it->second->obtain();
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(
+        bool value)  {
+    return obtainInt32(value);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
+        VehiclePropertyType valueType, size_t vectorSize) const {
+    return RecyclableType {
+        createVehiclePropValue(valueType, vectorSize).release(),
+        mDisposableDeleter
+    };
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(
+        VehiclePropertyType type) {
+    return obtain(type, 1);
+}
+
+
+void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) {
+    if (o == nullptr) {
+        ALOGE("Attempt to recycle nullptr");
+        return;
+    }
+
+    if (!check(&o->value)) {
+        ALOGE("Discarding value for prop 0x%x because it contains "
+                  "data that is not consistent with this pool. "
+                  "Expected type: %d, vector size: %d",
+              o->prop, mPropType, mVectorSize);
+        delete o;
+    } else {
+        ObjectPool<VehiclePropValue>::recycle(o);
+    }
+}
+
+bool VehiclePropValuePool::InternalPool::check(VehiclePropValue::RawValue* v) {
+    return check(&v->int32Values,
+                 (VehiclePropertyType::INT32 == mPropType
+                  || VehiclePropertyType::INT32_VEC == mPropType
+                  || VehiclePropertyType::BOOLEAN == mPropType))
+           && check(&v->floatValues,
+                    (VehiclePropertyType::FLOAT == mPropType
+                     || VehiclePropertyType::FLOAT_VEC == mPropType))
+           && check(&v->int64Values,
+                    VehiclePropertyType::INT64 == mPropType)
+           && check(&v->bytes,
+                    VehiclePropertyType::BYTES == mPropType)
+           && v->stringValue.size() == 0;
+}
+
+VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
+    return createVehiclePropValue(mPropType, mVectorSize).release();
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h
new file mode 100644
index 0000000..d9231c3
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleObjectPool.h
@@ -0,0 +1,244 @@
+/*
+ * 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.
+ */
+
+
+#ifndef android_hardware_vehicle_V2_0_VehicleObjectPool_H_
+#define android_hardware_vehicle_V2_0_VehicleObjectPool_H_
+
+#include <deque>
+#include <map>
+#include <mutex>
+
+#include <android/hardware/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+// Handy metric mostly for unit tests and debug.
+#define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++;
+struct PoolStats {
+    std::atomic<uint32_t> Obtained {0};
+    std::atomic<uint32_t> Created {0};
+    std::atomic<uint32_t> Recycled {0};
+
+    static PoolStats* instance() {
+        static PoolStats inst;
+        return &inst;
+    }
+};
+
+template<typename T>
+struct Deleter  {
+    using OnDeleteFunc = std::function<void(T*)>;
+
+    Deleter(const OnDeleteFunc& f) : mOnDelete(f) {};
+
+    Deleter() = default;
+    Deleter(const Deleter&) = default;
+
+    void operator()(T* o) {
+        mOnDelete(o);
+    }
+private:
+    OnDeleteFunc mOnDelete;
+};
+
+/**
+ * This is std::unique_ptr<> with custom delete operation that typically moves
+ * the pointer it holds back to ObjectPool.
+ */
+template <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+/**
+ * Generic abstract object pool class. Users of this class must implement
+ * #createObject method.
+ *
+ * This class is thread-safe. Concurrent calls to #obtain(...) method from
+ * multiple threads is OK, also client can obtain an object in one thread and
+ * then move ownership to another thread.
+ *
+ */
+template<typename T>
+class ObjectPool {
+public:
+    ObjectPool() = default;
+    virtual ~ObjectPool() = default;
+
+    virtual recyclable_ptr<T> obtain() {
+        std::lock_guard<std::mutex> g(mLock);
+        INC_METRIC_IF_DEBUG(Obtained)
+        if (mObjects.empty()) {
+            INC_METRIC_IF_DEBUG(Created)
+            return wrap(createObject());
+        }
+
+        auto o = wrap(mObjects.front().release());
+        mObjects.pop_front();
+
+        return o;
+    }
+
+    ObjectPool& operator =(const ObjectPool &) = delete;
+    ObjectPool(const ObjectPool &) = delete;
+
+protected:
+    virtual T* createObject() = 0;
+
+    virtual void recycle(T* o) {
+        INC_METRIC_IF_DEBUG(Recycled)
+        std::lock_guard<std::mutex> g(mLock);
+        mObjects.push_back(std::unique_ptr<T> { o } );
+    }
+
+private:
+    const Deleter<T>& getDeleter() {
+        if (!mDeleter.get()) {
+            Deleter<T> *d = new Deleter<T>(std::bind(
+                &ObjectPool::recycle, this, std::placeholders::_1));
+            mDeleter.reset(d);
+        }
+        return *mDeleter.get();
+    }
+
+    recyclable_ptr<T> wrap(T* raw) {
+        return recyclable_ptr<T> { raw, getDeleter() };
+    }
+
+private:
+    mutable std::mutex mLock;
+    std::deque<std::unique_ptr<T>> mObjects;
+    std::unique_ptr<Deleter<T>> mDeleter;
+};
+
+/**
+ * This class provides a pool of recycable VehiclePropertyValue objects.
+ *
+ * It has only one overloaded public method - obtain(...), users must call this
+ * method when new object is needed with given VehiclePropertyType and vector
+ * size (for vector properties). This method returns a recycable smart pointer
+ * to VehiclePropertyValue, essentially this is a std::unique_ptr with custom
+ * delete function, so recycable object has only one owner and developers can
+ * safely pass it around. Once this object goes out of scope, it will be
+ * returned the the object pool.
+ *
+ * Some objects are not recycable: strings and vector data types with
+ * vector length > maxRecyclableVectorSize (provided in the constructor). These
+ * objects will be deleted immediately once the go out of scope. There's no
+ * synchornization penalty for these objects since we do not store them in the
+ * pool.
+ *
+ * This class is thread-safe. Users can obtain an object in one thread and pass
+ * it to another.
+ *
+ * Sample usage:
+ *
+ *   VehiclePropValuePool pool;
+ *   auto v = pool.obtain(VehiclePropertyType::INT32);
+ *   v->propId = VehicleProperty::HVAC_FAN_SPEED;
+ *   v->areaId = VehicleAreaZone::ROW_1_LEFT;
+ *   v->timestamp = elapsedRealtimeNano();
+ *   v->value->int32Values[0] = 42;
+ *
+ *
+ */
+class VehiclePropValuePool {
+public:
+    using RecyclableType = recyclable_ptr<VehiclePropValue>;
+
+    /**
+     * Creates VehiclePropValuePool
+     *
+     * @param maxRecyclableVectorSize - vector value types (e.g.
+     * VehiclePropertyType::INT32_VEC) with size equal or less to this value
+     * will be stored in the pool. If users tries to obtain value with vector
+     * size greater than maxRecyclableVectorSize user will receive appropriate
+     * object, but once it goes out of scope it will be deleted immediately, not
+     * returning back to the object pool.
+     *
+     */
+    VehiclePropValuePool(size_t maxRecyclableVectorSize = 4) :
+        mMaxRecyclableVectorSize(maxRecyclableVectorSize) {};
+
+    RecyclableType obtain(VehiclePropertyType type);
+
+    RecyclableType obtain(VehiclePropertyType type, size_t vecSize);
+    RecyclableType obtain(const VehiclePropValue& src);
+    RecyclableType obtainBoolean(bool value);
+    RecyclableType obtainInt32(int32_t value);
+    RecyclableType obtainInt64(int64_t value);
+    RecyclableType obtainFloat(float value);
+    RecyclableType obtainString(const char* cstr);
+    RecyclableType obtainComplex();
+
+    VehiclePropValuePool(VehiclePropValuePool& ) = delete;
+    VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
+private:
+    bool isDisposable(VehiclePropertyType type, size_t vecSize) const {
+        return vecSize > mMaxRecyclableVectorSize ||
+               VehiclePropertyType::STRING == type ||
+               VehiclePropertyType::COMPLEX == type;
+    }
+
+    RecyclableType obtainDisposable(VehiclePropertyType valueType,
+                                    size_t vectorSize) const;
+    RecyclableType obtainRecylable(VehiclePropertyType type,
+                                   size_t vecSize);
+
+    class InternalPool: public ObjectPool<VehiclePropValue> {
+    public:
+        InternalPool(VehiclePropertyType type, size_t vectorSize)
+            : mPropType(type), mVectorSize(vectorSize) {}
+
+        RecyclableType obtain() {
+            return ObjectPool<VehiclePropValue>::obtain();
+        }
+    protected:
+        VehiclePropValue* createObject() override;
+        void recycle(VehiclePropValue* o) override;
+    private:
+        bool check(VehiclePropValue::RawValue* v);
+
+        template <typename VecType>
+        bool check(hidl_vec<VecType>* vec, bool expected) {
+            return vec->size() == (expected ? mVectorSize : 0);
+        }
+    private:
+        VehiclePropertyType mPropType;
+        size_t mVectorSize;
+    };
+
+private:
+    const Deleter<VehiclePropValue> mDisposableDeleter {
+        [] (VehiclePropValue* v) {
+            delete v;
+        }
+    };
+
+private:
+    mutable std::mutex mLock;
+    const size_t mMaxRecyclableVectorSize;
+    std::map<int32_t, std::unique_ptr<InternalPool>> mValueTypePools;
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_vehicle_V2_0_VehicleObjectPool_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehiclePropConfigIndex.h b/vehicle/2.0/default/vehicle_hal_manager/VehiclePropConfigIndex.h
new file mode 100644
index 0000000..540fc33
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehiclePropConfigIndex.h
@@ -0,0 +1,78 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_VehiclePropConfigIndex_H_
+#define android_hardware_vehicle_V2_0_VehiclePropConfigIndex_H_
+
+#include <utils/KeyedVector.h>
+
+#include <android/hardware/vehicle/2.0/IVehicle.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+/*
+ * This is thread-safe immutable class to hold vehicle property configuration
+ * data.
+ */
+class VehiclePropConfigIndex {
+public:
+    VehiclePropConfigIndex(
+        const std::vector<VehiclePropConfig>& properties)
+        : mConfigs(properties), mPropToConfig(mConfigs)
+    {}
+
+    bool hasConfig(VehicleProperty property) const {
+        return mPropToConfig.indexOfKey(property) >= 0;
+    }
+
+    const VehiclePropConfig& getConfig(VehicleProperty property) const {
+        return *mPropToConfig.valueFor(property);
+    }
+
+    const std::vector<VehiclePropConfig>& getAllConfigs() const {
+        return mConfigs;
+    }
+
+private:
+    typedef KeyedVector<VehicleProperty, const VehiclePropConfig*> PropConfigMap;
+    class ImmutablePropConfigMap : private PropConfigMap {
+    public:
+        ImmutablePropConfigMap(const std::vector<VehiclePropConfig>& configs) {
+            setCapacity(configs.size());
+            for (auto& config : configs) {
+                add(config.prop, &config);
+            }
+        }
+    public:
+        using PropConfigMap::valueFor;
+        using PropConfigMap::indexOfKey;
+    };
+
+private:
+    const std::vector<VehiclePropConfig> mConfigs;
+    const ImmutablePropConfigMap mPropToConfig;  // mConfigs must be declared
+                                                 // first.
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_vehicle_V2_0_VehiclePropConfigIndex_H_
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp
new file mode 100644
index 0000000..5a00631
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.vehicle@2.0-impl"
+
+#include "VehicleUtils.h"
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+//namespace utils {
+
+std::unique_ptr<VehiclePropValue> createVehiclePropValue(
+    VehiclePropertyType type, size_t vecSize) {
+    auto val = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
+    switch (type) {
+        case VehiclePropertyType::INT32:      // fall through
+        case VehiclePropertyType::INT32_VEC:  // fall through
+        case VehiclePropertyType::BOOLEAN:
+            val->value.int32Values.resize(vecSize);
+            break;
+        case VehiclePropertyType::FLOAT:      // fall through
+        case VehiclePropertyType::FLOAT_VEC:
+            val->value.floatValues.resize(vecSize);
+            break;
+        case VehiclePropertyType::INT64:
+            val->value.int64Values.resize(vecSize);
+            break;
+        case VehiclePropertyType::BYTES:
+            val->value.bytes.resize(vecSize);
+            break;
+        case VehiclePropertyType::STRING:
+        case VehiclePropertyType::COMPLEX:
+            break; // Valid, but nothing to do.
+        default:
+            ALOGE("createVehiclePropValue: unknown type: %d", type);
+            val.reset(nullptr);
+    }
+    return val;
+}
+
+size_t getVehicleRawValueVectorSize(
+    const VehiclePropValue::RawValue& value, VehiclePropertyType type) {
+    switch (type) {
+        case VehiclePropertyType::INT32:      // fall through
+        case VehiclePropertyType::INT32_VEC:  // fall through
+        case VehiclePropertyType::BOOLEAN:
+            return value.int32Values.size();
+        case VehiclePropertyType::FLOAT:      // fall through
+        case VehiclePropertyType::FLOAT_VEC:
+            return value.floatValues.size();
+        case VehiclePropertyType::INT64:
+            return value.int64Values.size();
+        case VehiclePropertyType::BYTES:
+            return value.bytes.size();
+        default:
+            return 0;
+    }
+}
+
+template<typename T>
+inline void copyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
+    for (size_t i = 0; i < std::min(dest->size(), src.size()); i++) {
+        (*dest)[i] = src[i];
+    }
+}
+
+void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
+                         const VehiclePropValue::RawValue& src) {
+    dest->int32Values = src.int32Values;
+    dest->floatValues = src.floatValues;
+    dest->int64Values = src.int64Values;
+    dest->bytes = src.bytes;
+    dest->stringValue = src.stringValue;
+}
+
+template<typename T>
+void shallowCopyHidlVec(hidl_vec <T>* dest, const hidl_vec <T>& src) {
+    if (src.size() > 0) {
+        dest->setToExternal(const_cast<T*>(&src[0]), src.size());
+    } else if (dest->size() > 0) {
+        dest->resize(0);
+    }
+}
+
+void shallowCopyHidlStr(hidl_string* dest, const hidl_string& src) {
+    if (!src.empty()) {
+        dest->setToExternal(src.c_str(), src.size());
+    } else if (dest->size() > 0) {
+        dest->setToExternal(0, 0);
+    }
+}
+
+void shallowCopy(VehiclePropValue* dest, const VehiclePropValue& src) {
+    dest->prop = src.prop;
+    dest->areaId = src.areaId;
+    dest->timestamp = src.timestamp;
+    shallowCopyHidlVec(&dest->value.int32Values, src.value.int32Values);
+    shallowCopyHidlVec(&dest->value.int64Values, src.value.int64Values);
+    shallowCopyHidlVec(&dest->value.floatValues, src.value.floatValues);
+    shallowCopyHidlVec(&dest->value.bytes, src.value.bytes);
+    shallowCopyHidlStr(&dest->value.stringValue, src.value.stringValue);
+}
+
+
+//}  // namespace utils
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
diff --git a/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.h b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.h
new file mode 100644
index 0000000..1177ddd
--- /dev/null
+++ b/vehicle/2.0/default/vehicle_hal_manager/VehicleUtils.h
@@ -0,0 +1,86 @@
+/*
+ * 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.
+ */
+
+#ifndef android_hardware_vehicle_V2_0_VehicleUtils_H_
+#define android_hardware_vehicle_V2_0_VehicleUtils_H_
+
+#include <memory>
+
+#include <hidl/HidlSupport.h>
+
+#include <android/hardware/vehicle/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace vehicle {
+namespace V2_0 {
+
+/** Represents all supported areas for a property. Can be used is  */
+constexpr int32_t kAllSupportedAreas = 0;
+
+/** Returns underlying (integer) value for given enum. */
+template<typename ENUM>
+inline typename std::underlying_type<ENUM>::type toInt(ENUM const value) {
+    return static_cast<typename std::underlying_type<ENUM>::type>(value);
+}
+
+inline VehiclePropertyType getPropType(VehicleProperty prop) {
+    return static_cast<VehiclePropertyType>(
+        static_cast<int32_t>(prop)
+        & static_cast<int32_t>(VehiclePropertyType::MASK));
+}
+
+inline VehiclePropertyGroup getPropGroup(VehicleProperty prop) {
+    return static_cast<VehiclePropertyGroup>(
+        static_cast<int32_t>(prop)
+        & static_cast<int32_t>(VehiclePropertyGroup::MASK));
+}
+
+inline VehicleArea getPropArea(VehicleProperty prop) {
+    return static_cast<VehicleArea>(
+        static_cast<int32_t>(prop) & static_cast<int32_t>(VehicleArea::MASK));
+}
+
+inline bool isGlobalProp(VehicleProperty prop) {
+    return getPropArea(prop) == VehicleArea::GLOBAL;
+}
+
+inline bool isSystemProperty(VehicleProperty prop) {
+    return VehiclePropertyGroup::SYSTEM == getPropGroup(prop);
+}
+
+std::unique_ptr<VehiclePropValue> createVehiclePropValue(
+    VehiclePropertyType type, size_t vecSize);
+
+size_t getVehicleRawValueVectorSize(
+    const VehiclePropValue::RawValue& value, VehiclePropertyType type);
+
+void copyVehicleRawValue(VehiclePropValue::RawValue* dest,
+                                const VehiclePropValue::RawValue& src);
+
+template<typename T>
+void shallowCopyHidlVec(hidl_vec<T>* dest, const hidl_vec<T>& src);
+
+void shallowCopyHidlStr(hidl_string* dest, const hidl_string& src);
+
+void shallowCopy(VehiclePropValue* dest, const VehiclePropValue& src);
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace hardware
+}  // namespace android
+
+#endif // android_hardware_vehicle_V2_0_VehicleUtils_H_
diff --git a/vehicle/2.0/types.hal b/vehicle/2.0/types.hal
new file mode 100644
index 0000000..a9b706d
--- /dev/null
+++ b/vehicle/2.0/types.hal
@@ -0,0 +1,3045 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vehicle@2.0;
+
+/*
+ * Enumerates supported data types for VehicleProperty.
+ *
+ * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ */
+enum VehiclePropertyType : int32_t {
+    STRING         = 0x00100000,
+    BOOLEAN        = 0x00200000,
+    INT32          = 0x00400000,
+    INT32_VEC      = 0x00410000,
+    INT64          = 0x00500000,
+    FLOAT          = 0x00600000,
+    FLOAT_VEC      = 0x00610000,
+    BYTES          = 0x00700000,
+
+    /*
+     * Any combination of scalar or vector types. The exact format must be
+     * provided in the description of the property.
+     */
+    COMPLEX        = 0x00e00000,
+
+    MASK           = 0x00ff0000
+};
+
+/*
+ * Some properties may be associated with particular vehicle areas. For
+ * example, VehicleProperty:DOOR_LOCK property must be associated with
+ * particular door, thus this property must be marked with
+ * VehicleArea:DOOR flag.
+ *
+ * Other properties may not be associated with particular vehicle area,
+ * these kind of properties must have VehicleArea:GLOBAL flag.
+ *
+ * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ */
+enum VehicleArea : int32_t {
+      GLOBAL       = 0x01000000,
+      ZONE         = 0x02000000,
+      WINDOW       = 0x03000000,
+      MIRROR       = 0x04000000,
+      SEAT         = 0x05000000,
+      DOOR         = 0x06000000,
+
+      MASK         = 0x0f000000,
+};
+
+/*
+ * Enumerates property groups.
+ *
+ * This is a bitwise flag that supposed to be used in VehicleProperty enum.
+ */
+enum VehiclePropertyGroup : int32_t {
+    /*
+     * Properties declared in AOSP must have this flag.
+     */
+    SYSTEM         = 0x10000000,
+
+    /*
+     * Properties declared by vendors must have this flag.
+     */
+    VENDOR         = 0x20000000,
+
+    MASK           = 0xf0000000,
+};
+
+/*
+ * Declares all vehicle properties. VehicleProperty has a bitwise structure.
+ * Each property must have:
+ *   - an unique id from range 0x0100 - 0xffff
+ *   - associated data type using VehiclePropertyType
+ *   - property group (VehiclePropertyGroup)
+ *   - vehicle area (VehicleArea)
+ *
+ * Vendors are allowed to extend this enum with their own properties. In this
+ * case they must use VehiclePropertyGroup:VENDOR flag when property is
+ * declared.
+ */
+enum VehicleProperty: int32_t {
+
+    /* Undefined property. */
+    INVALID = 0x00000000,
+
+    /*
+     * VIN of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_VIN= (
+        0x0100
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Maker name of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_MAKE = (
+        0x0101
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Model of vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_MODEL = (
+        0x0102
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Model year of vehicle.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:YEAR
+     */
+    INFO_MODEL_YEAR = (
+        0x0103
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Fuel capacity of the vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLILITER
+     */
+    INFO_FUEL_CAPACITY = (
+        0x0104
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Current odometer value of the vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE | VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:KILOMETER
+     */
+    PERF_ODOMETER = (
+        0x0204
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Speed of the vehicle
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:METER_PER_SEC
+     */
+    PERF_VEHICLE_SPEED = (
+        0x0207
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Temperature of engine coolant
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELCIUS
+     */
+    ENGINE_COOLANT_TEMP = (
+        0x0301
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Temperature of engine oil
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELCIUS
+     */
+    ENGINE_OIL_TEMP = (
+        0x0304
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Engine rpm
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:RPM
+     */
+    ENGINE_RPM = (
+        0x0305
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Currently selected gear
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleGear
+     */
+    GEAR_SELECTION = (
+        0x0400
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Current gear. In non-manual case, selected gear does not necessarily
+     * match the current gear.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleGear
+     */
+    CURRENT_GEAR = (
+        0x0401
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Parking brake state.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    PARKING_BRAKE_ON = (
+        0x0402
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Driving status policy.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum VehicleDrivingStatus
+     */
+    DRIVING_STATUS = (
+        0x0404
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Warning for fuel low level.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    FUEL_LEVEL_LOW = (
+        0x0405
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Night mode or not.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    NIGHT_MODE = (
+        0x0407
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * State of the vehicles turn signals
+     *
+     * Values from VehicleTurnSignal
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    TURN_SIGNAL_STATE = (
+        0x0408
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Represents ignition state
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    IGNITION_STATE = (
+        0x0409
+            | VehiclePropertyGroup:SYSTEM
+            | VehiclePropertyType:INT32
+            | VehicleArea:GLOBAL),
+
+    /*
+     * Fan speed setting
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @allow_out_of_range_value : OFF
+     */
+    HVAC_FAN_SPEED = (
+        0x0500
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:ZONE),
+
+    /*
+     * Fan direction setting
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @data_enum VehicleHvacFanDirection
+     * @allow_out_of_range_value : OFF
+     */
+    HVAC_FAN_DIRECTION = (
+        0x0501
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:ZONE),
+
+    /*
+     * HVAC current temperature.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_TEMPERATURE_CURRENT = (
+        0x0502
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:ZONE),
+
+    /*
+     * HVAC, target temperature set.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @allow_out_of_range_value : MIN / MAX / OFF
+     */
+    HVAC_TEMPERATURE_SET = (
+        0x0503
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off defrost
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_DEFROSTER = (
+        0x0504
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:WINDOW),
+
+    /*
+     * On/off AC
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags Supported zones
+     */
+    HVAC_AC_ON = (
+        0x0505
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off max AC
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_MAX_AC_ON = (
+        0x0506
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off max defrost
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_MAX_DEFROST_ON = (
+        0x0507
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off re-circulation
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_RECIRC_ON = (
+        0x0508
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off dual. This must be defined per each row.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_DUAL_ON = (
+        0x0509
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * On/off automatic mode
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_AUTO_ON = (
+        0x050A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * Seat temperature
+     *
+     * Negative values indicate cooling.
+     * 0 indicates off.
+     * Positive values indicate heating.
+     *
+     * Some vehicles may have multiple levels of heating and cooling. The
+     * min/max range defines the allowable range and number of steps in each
+     * direction.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    HVAC_SEAT_TEMPERATURE = (
+        0x050B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /**
+     * Side Mirror Heat
+     *
+     * Increase values denote higher heating levels for side mirrors.
+     * 0 indicates heating is turned off.
+     *
+     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ_WRITE
+     */
+    HVAC_SIDE_MIRROR_HEAT = (
+        0x050C
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:MIRROR),
+
+    /**
+     * Steering Wheel Temperature
+     *
+     * Sets the temperature for the steering wheel
+     * Positive value indicates heating.
+     * Negative value indicates cooling.
+     * 0 indicates temperature control is off.
+     *
+     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ_WRITE
+     */
+    HVAC_STEERING_WHEEL_TEMP = (
+        0x050D
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Temperature units
+     *
+     * Indicates whether the temperature is in Celsius, Fahrenheit, or a
+     * different unit from VehicleUnit enum.
+     * This parameter affects all HVAC temperatures in the system.
+     *
+     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ
+     */
+    HVAC_TEMPERATURE_UNITS = (
+        0x050E
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:ZONE),
+
+    /**
+     * Actual fan speed
+     *
+     * @change_mode VEHICLE_PROP_CHANGE_MODE_ON_CHANGE
+     * @access VEHICLE_PROP_ACCESS_READ
+     * @allow_out_of_range_value : OFF
+     */
+    HVAC_ACTUAL_FAN_SPEED_RPM = (
+        0x050F
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:ZONE),
+
+    /**
+     * 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)
+     *
+     * @change_mode VEHICLE_PROP_CHANGE_MODE_STATIC
+     * @access VEHICLE_PROP_ACCESS_READ
+     * @allow_out_of_range_value : OFF
+     */
+    HVAC_FAN_DIRECTION_AVAILABLE = (
+        0x0511
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:ZONE),
+
+    /*
+     * Represents power state for HVAC. Some HVAC properties must require
+     * matching power to be turned on to get out of OFF state. For non-zoned
+     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_string list of HVAC properties whose power is controlled by this
+     *                property. Format is hexa-decimal number (0x...) separated
+     *                by comma like "0x500,0x503". All zones defined in these
+     *                affected properties must be available in the property.
+     */
+    HVAC_POWER_ON = (
+        0x0510
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /*
+     * Outside temperature
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELCIUS
+     */
+    ENV_OUTSIDE_TEMPERATURE = (
+        0x0703
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Cabin temperature
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:CELCIUS
+     */
+    ENV_CABIN_TEMPERATURE = (
+        0x0704
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Radio presets stored on the Car radio module. The data type used is int32
+     * array with the following fields:
+     * <ul>
+     *    <li> int32Values[0]: Preset number </li>
+     *    <li> int32Values[1]: Band type (see #RADIO_BAND_FM in
+     *    system/core/include/system/radio.h).
+     *    <li> int32Values[2]: Channel number </li>
+     *    <li> int32Values[3]: Sub channel number </li>
+     * </ul>
+     *
+     * NOTE: When getting a current preset config ONLY set preset number (i.e.
+     * int32Values[0]). For setting a preset other fields are required.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags Number of presets supported
+     */
+    RADIO_PRESET = (
+        0x0801
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Represents audio focus state of Android side. Note that car's audio
+     * module must own audio focus and grant audio focus to Android side when
+     * requested by Android side. The focus has both per stream characteristics
+     * and global characteristics.
+     *
+     * Focus request (get of this property) must take the following form:
+     *   int32Values[0]: VehicleAudioFocusRequest type
+     *   int32Values[1]: bit flags of streams requested by this focus request.
+     *                   There can be up to 32 streams.
+     *   int32Values[2]: External focus state flags. For request, only flag like
+     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG or
+     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG can be
+     *                   used.
+     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG is for case
+     *                   like radio where android side app still needs to hold
+     *                   focus but playback is done outside Android.
+     *                   VehicleAudioExtFocusFlag#MUTE_MEDIA_FLAG is for
+     *                   muting media channel including radio.
+     *                   VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG can be set
+     *                   even if android side releases focus (request type
+     *                   REQUEST_RELEASE). In that case, audio module must
+     *                   maintain mute state until user's explicit action to
+     *                   play some media.
+     *   int32Values[3]: Currently active audio contexts. Use combination of
+     *                   flags from VehicleAudioContextFlag.
+     *                   This can be used as a hint to adjust audio policy or
+     *                   other policy decision.
+     *                   Note that there can be multiple context active at the
+     *                   same time. And android can send the same focus request
+     *                   type gain due to change in audio contexts.
+     * Note that each focus request can request multiple streams that is
+     * expected to be used for the current request. But focus request itself
+     * is global behavior as GAIN or GAIN_TRANSIENT expects all sounds played
+     * by car's audio module to stop. Note that stream already allocated to
+     * android before this focus request must not be affected by focus
+     * request.
+     *
+     * Focus response (set and subscription callback for this property) must
+     * take the following form:
+     *   int32Values[0]: VehicleAudioFocusState type
+     *   int32Values[1]: bit flags of streams allowed.
+     *   int32Values[2]: External focus state: bit flags of currently active
+     *                   audio focus in car side (outside Android). Active
+     *                   audio focus does not necessarily mean currently
+     *                   playing, but represents the state of having focus or
+     *                   waiting for focus (pause state).
+     *                   One or combination of flags from
+     *                   VehicleAudioExtFocusFlag.
+     *                   0 means no active audio focus holder outside Android.
+     *                   The state must have following values for each
+     *                   VehicleAudioFocusState:
+     *                   GAIN: 0 or VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
+     *                       when radio is active in Android side.
+     *                   GAIN_TRANSIENT: 0. Can be
+     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG or
+     *                       VehicleAudioExtFocusFlag#TRANSIENT_FLAG if android
+     *                       side has requested
+     *                       REQUEST_GAIN_TRANSIENT_MAY_DUCK and car side is
+     *                       ducking.
+     *                   LOSS: 0 when no focus is audio is active in car side.
+     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG when car
+     *                       side is playing something permanent.
+     *                   LOSS_TRANSIENT: always must be
+     *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
+     *   int32Values[3]: context requested by android side when responding to
+     *                   focus request. When car side is taking focus away,
+     *                   this must be zero.
+     *
+     * A focus response must be sent per each focus request even if there is
+     * no change in focus state. This can happen in case like focus request
+     * only involving context change where android side still needs matching
+     * focus response to confirm that audio module has made necessary changes.
+     *
+     * If car does not support AUDIO_FOCUS, focus is assumed to be granted
+     * always.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    AUDIO_FOCUS = (
+        0x0900
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * A property to allow external component to control audio focus. Depending on
+     * H/W architecture, audio HAL may need to control audio focus while vehicle
+     * HAL is still interacting with upper layer. In such case, audio HAL may set
+     * this property and vehicle HAL may use this property value to decide
+     * response sent through AUDIO_FOCUS property.
+     * Data format is the same as AUDIO_FOCUS property.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    AUDIO_FOCUS_EXT_SYNC = (
+        0x0910
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to control audio volume of each audio context.
+     *
+     * VehiclePropConfig
+     *   configArray[0] : bit flags of all supported audio contexts from
+     *                    VehicleAudioContextFlag. If this is 0, audio volume is
+     *                    controlled per physical stream.
+     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
+     *                    represent audio module's capability.
+     *   configArray[2..3] : reserved
+     *   configArray[4..N+3] : maximum values for each audio context, where N is
+     *                         the number of audio contexts provided in
+     *                         configArray[0], minimum value is always 0 which
+     *                         indicates mute state.
+     *
+     * Data type looks like:
+     *   int32Values[0] : stream context as defined in VehicleAudioContextFlag.
+     *                    If only physical stream is supported
+     *                    (configArray[0] == 0), this must represent physical
+     *                    stream number.
+     *   int32Values[1] : volume level, valid range is 0 (mute) to max level
+     *                    defined in the config.
+     *   int32Values[2] : One of VehicleAudioVolumeState.
+     *
+     * This property requires per stream based get. HAL implementation must
+     * check stream number in get call to return the right volume.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags all audio contexts supported.
+     */
+    AUDIO_VOLUME = (
+        0x0901
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to allow audio volume sync from external components like audio HAL.
+     * Some vehicle HAL implementation may get volume control from audio HAL and in such
+     * case, setting AUDIO_VOLUME_EXT_SYNC property may trigger event in AUDIO_VOLUME property.
+     * Data format for this property is the same as AUDIO_VOLUME property.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags all audio contexts supported.
+     */
+    AUDIO_VOLUME_EXT_SYNC = (
+        0x0911
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property for handling volume limit set by user. This limits maximum
+     * volume that can be set per each context or physical stream.
+     *
+     * VehiclePropConfig
+     *   configArray[0] : bit flags of all supported audio contexts. If this is
+     *                    0, audio volume is controlled per physical stream.
+     *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag
+     *                    to represent audio module's capability.
+     *
+     * Data type looks like:
+     *   int32Values[0] : stream context as defined in VehicleAudioFocusFlag.
+     *                    If only physical stream is supported
+     *                    (configArray[0] == 0), this must represent physical
+     *                    stream number.
+     *   int32Values[1] : maximum volume set to the stream. If there is no
+     *                    restriction, this value must be  bigger than
+     *                    AUDIO_VOLUME's max value.
+     *
+     * If car does not support this feature, this property must not be
+     * populated by HAL.
+     * This property requires per stream based get. HAL implementation must
+     * check stream number in get call to return the right volume.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_flags all audio contexts supported.
+     */
+    AUDIO_VOLUME_LIMIT = (
+        0x0902
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to share audio routing policy of android side. This property is
+     * set at the beginning to pass audio policy in android side down to
+     * vehicle HAL and car audio module.
+     * This can be used as a hint to adjust audio policy or other policy
+     * decision.
+     *
+     *   int32Values[0] : audio stream where the audio for the application
+     *                    context must be routed by default. Note that this is
+     *                    the default setting from system, but each app may
+     *                    still use different audio stream for whatever reason.
+     *   int32Values[1] : All audio contexts that must be sent through the
+     *                     physical stream. Flag is defined in
+     *                     VehicleAudioFocusFlag.
+
+     * Setting of this property must be done for all available physical streams
+     * based on audio H/W variant information acquired from AUDIO_HW_VARIANT
+     * property.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    AUDIO_ROUTING_POLICY = (
+        0x0903
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to return audio H/W variant type used in this car. This allows
+     * android side to support different audio policy based on H/W variant used.
+     * Note that other components like CarService may need overlay update to
+     * support additional variants. If this property does not
+     * exist, default audio policy must be used.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @config_flags Additional info on audio H/W. Must use
+     *               VehicleAudioHwVariantConfigFlag for this.
+     */
+    AUDIO_HW_VARIANT = (
+        0x0904
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to pass hint on external audio routing. When android side
+     * request focus with VehicleAudioExtFocusflag, this
+     * property must be set before setting AUDIO_FOCUS property as a hint for
+     * external audio source routing.
+     * Note that setting this property alone must not trigger any change.
+     * Audio routing must be changed only when AUDIO_FOCUS property is set.
+     * Note that this property allows passing custom value as long as it is
+     * defined in VehiclePropConfig#configString. This allows supporting
+     * non-standard routing options through this property.
+     * It is recommended to use separate name space for custom property to
+     * prevent conflict in future android releases.
+     * Enabling each external routing option is done by enabling each bit flag
+     * for the routing.
+     * This property can support up to 128 external routings.
+     * To give full flexibility, there is no standard definition for each bit
+     * flag and assigning each big flag to specific routing type is decided by
+     * VehiclePropConfig#configString.  VehiclePropConfig#configString has
+     * format of each entry separated by ',' and each entry has format of
+     * bitFlagPositon:typeString[:physicalStreamNumber].
+     *  bitFlagPosition: represents which big flag will be set to enable this
+     *  routing. 0 means
+     *    LSB in int32Values[0]. 31 will be MSB in int32Values[0]. 127 will MSB
+     *    in int32Values[3].
+     *  typeString: string representation of external routing. Some types are
+     *    already defined in AUDIO_EXT_ROUTING_SOURCE_* and use them first
+     *    before adding something custom. Applications will find each routing
+     *    using this string.
+     *  physicalStreamNumber: This part is optional and represents physical
+     *    stream to android which will be disabled when this routing is enabled.
+     *    If not specified, this routing must not affect physical streams to
+     *    android.
+     * As an example, let's assume a system with two physical streams, 0 for
+     * media and 1 for nav guidance. And let's assume external routing option
+     * of am fm radio, external navigation guidance, satellite radio, and one
+     * custom. Let's assume that radio and satellite replaces physical stream 0
+     * and external navigation replaces physical stream 1. And bit flag will be
+     * assigned in the order listed above. This configuration will look like
+     * this in config_string:
+     *  "0:RADIO_AM_FM:0,1:EXT_NAV_GUIDANCE:1,2:RADIO_SATELLITE:0,3:com.test.SOMETHING_CUSTOM"
+     * When android requests RADIO_AM_FM, int32Values[0] will be set to 0x1.
+     * When android requests RADIO_SATELLITE + EXT_NAV_GUIDANCE, int32Values[0]
+     * will be set to 0x2|0x4.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_string List of all avaiable external source in the system.
+     */
+    AUDIO_EXT_ROUTING_HINT = (
+        0x0905
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Represents state of audio stream. Audio HAL should set this when a stream is starting or
+     * ending. Car service can request focus for audio played without focus. If such feature
+     * is not required, this property does not need to be implemented.
+     * Car service only monitors setting of this property. It is up to each vehicle HAL
+     * implementation to add necessary action but default implementation will be doing nothing on
+     * this propery's set from audio HAL.
+     * Actual streaming of data should be done only after getting focus for the given stream from
+     * car audio module. Focus can be already granted when stream is started. Focus state can be
+     * monitored by monitoring AUDIO_FOCUS property. If car does not support
+     * AUDIO_FOCUS property, there is no need to monitor focus as focus is assumed to be
+     * granted always.
+     * Data has the following format:
+     *   int32_array[0] : vehicle_audio_stream_state, 0: stopped, 1: started
+     *   int32_array[1] : stream number like 0, 1, 2, ...
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    AUDIO_STREAM_STATE  = (
+        0x0906
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Property to control car specific audio parameters. Each parameter is defined as string key-
+     * value pair.
+     * set and event notification can pass multiple parameters using the
+     * following format:
+     *   key1=value1;key2=value2;...
+     * get call can request multiple parameters using the following format:
+     *   key1;key2;...
+     * Response for get call has the same format as set.
+     *
+     * VehiclePropConfig
+     *   configString: give list of all supported keys with ; as separator. For example:
+     *     key1;key2;...
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+    AUDIO_PARAMETERS = (
+        0x907
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:STRING
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Index in int32Values for AP_POWER_STATE property.
+     */
+    AP_POWER_STATE = (0x00000A00),
+
+  /*
+   * Property to represent brightness of the display. Some cars have single
+   * control for the brightness of all displays and this property is to share
+   * change in that control.
+   *
+   * If this is writable, android side can set this value when user changes
+   * display brightness from Settings. If this is read only, user may still
+   * change display brightness from Settings, but that will not be reflected
+   * to other displays.
+   *
+   * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+   * @access VehiclePropertyAccess:READ_WRITE
+   */
+    DISPLAY_BRIGHTNESS = (
+        0x0A01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to report bootup reason for the current power on. This is a
+     * static property that will not change for the whole duration until power
+     * off. For example, even if user presses power on button after automatic
+     * power on with door unlock, bootup reason must stay with 
+     * VehicleApPowerBootupReason#USER_UNLOCK.
+     *
+     * int32Values[0] must be VehicleApPowerBootupReason.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+    */
+    AP_POWER_BOOTUP_REASON = (
+        0x0A02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Property to feed H/W input events to android
+     *
+     * int32Values[0] : action defined by VehicleHwKeyInputAction
+     * int32Values[1] : key code, must use standard android key code
+     * int32Values[2] : target display defined in VehicleDisplay. Events not
+     *                  tied to specific display must be sent to
+     *                  VehicleDisplay#MAIN.
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @config_flags
+     */
+    HW_KEY_INPUT = (
+        0x0A10
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | 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 VehicleAudioFocusFlag
+     *                    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.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_SET
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:SECS
+     */
+    UNIX_TIME = (
+        0x0A30
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT64
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Current time only.
+     * Some vehicles may not keep track of date.  This property only affects
+     * the current time, in seconds during the day.  Thus, the max value for
+     * this parameter is 86,400 (24 * 60 * 60)
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_SET
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @unit VehicleUnit:SECS
+     */
+    CURRENT_TIME_IN_SECONDS = (
+        0x0A31
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Door position
+     *
+     * This is an integer in case a door may be set to a particular position.
+     * Max value indicates fully open, min value (0) indicates fully closed.
+     *
+     * Some vehicles (minivans) can open the door electronically.  Hence, the
+     * ability to write this property.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_POS = (
+        0x0B00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:DOOR),
+
+    /*
+     * Door move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_MOVE = (
+        0x0B01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:DOOR),
+
+    /*
+     * Door lock
+     *
+     * 'true' indicates door is locked
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    DOOR_LOCK = (
+        0x0B02
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:DOOR),
+
+    /*
+     * Mirror Z Position
+     *
+     * Positive value indicates tilt upwards, negative value is downwards
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Z_POS = (
+        0x0B40
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:MIRROR),
+
+    /*
+     * Mirror Z Move
+     *
+     * Positive value indicates tilt upwards, negative value is downwards
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Z_MOVE = (
+        0x0B41
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:MIRROR),
+
+    /*
+     * Mirror Y Position
+     *
+     * Positive value indicate tilt right, negative value is left
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Y_POS = (
+        0x0B42
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:MIRROR),
+
+    /*
+     * Mirror Y Move
+     *
+     * Positive value indicate tilt right, negative value is left
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_Y_MOVE = (
+        0x0B43
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:MIRROR),
+
+    /*
+     * Mirror Lock
+     *
+     * True indicates mirror positions are locked and not changeable
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_LOCK = (
+        0x0B44
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Mirror Fold
+     *
+     * True indicates mirrors are folded
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    MIRROR_FOLD = (
+        0x0B45
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Seat memory select
+     *
+     * This parameter selects the memory preset to use to select the seat
+     * position. The minValue is always 0, and the maxValue determines the
+     * number of seat positions available.
+     *
+     * For instance, if the driver's seat has 3 memory presets, the maxValue
+     * will be 3. When the user wants to select a preset, the desired preset
+     * number (1, 2, or 3) is set.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    SEAT_MEMORY_SELECT = (
+        0x0B80
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat memory set
+     *
+     * This setting allows the user to save the current seat position settings
+     * into the selected preset slot.  The maxValue for each seat position
+     * shall match the maxValue for SEAT_MEMORY_SELECT.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     */
+    SEAT_MEMORY_SET = (
+        0x0B81
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seatbelt buckled
+     *
+     * True indicates belt is buckled.
+     *
+     * Write access indicates automatic seat buckling capabilities.  There are
+     * no known cars at this time, but you never know...
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_BUCKLED = (
+        0x0B82
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:SEAT),
+
+    /*
+     * Seatbelt height position
+     *
+     * Adjusts the shoulder belt anchor point.
+     * Max value indicates highest position
+     * Min value indicates lowest position
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_HEIGHT_POS = (
+        0x0B83
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seatbelt height move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BELT_HEIGHT_MOVE = (
+        0x0B84
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat fore/aft position
+     *
+     * Sets the seat position forward (closer to steering wheel) and backwards.
+     * Max value indicates closest to wheel, min value indicates most rearward
+     * position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_FORE_AFT_POS = (
+        0x0B85
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat fore/aft move
+     *
+     * Moves the seat position forward and aft.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_FORE_AFT_MOVE = (
+        0x0B86
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat backrest angle 1 position
+     *
+     * Backrest angle 1 is the actuator closest to the bottom of the seat.
+     * Max value indicates angling forward towards the steering wheel.
+     * Min value indicates full recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_1_POS = (
+        0x0B87
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat backrest angle 1 move
+     *
+     * Moves the backrest forward or recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_1_MOVE = (
+        0x0B88
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat backrest angle 2 position
+     *
+     * Backrest angle 2 is the next actuator up from the bottom of the seat.
+     * Max value indicates angling forward towards the steering wheel.
+     * Min value indicates full recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_2_POS = (
+        0x0B89
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat backrest angle 2 move
+     *
+     * Moves the backrest forward or recline.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_BACKREST_ANGLE_2_MOVE = (
+        0x0B8A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat height position
+     *
+     * Sets the seat height.
+     * Max value indicates highest position.
+     * Min value indicates lowest position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEIGHT_POS = (
+        0x0B8B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat height move
+     *
+     * Moves the seat height.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEIGHT_MOVE = (
+        0x0B8C
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat depth position
+     *
+     * Sets the seat depth, distance from back rest to front edge of seat.
+     * Max value indicates longest depth position.
+     * Min value indicates shortest position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_DEPTH_POS = (
+        0x0B8D
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat depth move
+     *
+     * Adjusts the seat depth.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_DEPTH_MOVE = (
+        0x0B8E
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat tilt position
+     *
+     * Sets the seat tilt.
+     * Max value indicates front edge of seat higher than back edge.
+     * Min value indicates front edge of seat lower than back edge.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_TILT_POS = (
+        0x0B8F
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Seat tilt move
+     *
+     * Tilts the seat.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_TILT_MOVE = (
+        0x0B90
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Lumber fore/aft position
+     *
+     * Pushes the lumbar support forward and backwards
+     * Max value indicates most forward position.
+     * Min value indicates most rearward position.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_FORE_AFT_POS = (
+        0x0B91
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Lumbar fore/aft move
+     *
+     * Adjusts the lumbar support.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_FORE_AFT_MOVE = (
+        0x0B92
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Lumbar side support position
+     *
+     * Sets the amount of lateral lumbar support.
+     * Max value indicates widest lumbar setting (i.e. least support)
+     * Min value indicates thinnest lumbar setting.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_SIDE_SUPPORT_POS = (
+        0x0B93
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Lumbar side support move
+     *
+     * Adjusts the amount of lateral lumbar support.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_LUMBAR_SIDE_SUPPORT_MOVE = (
+        0x0B94
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Headrest height position
+     *
+     * Sets the headrest height.
+     * Max value indicates tallest setting.
+     * Min value indicates shortest setting.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_HEIGHT_POS = (
+        0x0B95
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Headrest height move
+     *
+     * Moves the headrest up and down.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_HEIGHT_MOVE = (
+        0x0B96
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Headrest angle position
+     *
+     * Sets the angle of the headrest.
+     * Max value indicates most upright angle.
+     * Min value indicates shallowest headrest angle.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_ANGLE_POS = (
+        0x0B97
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Headrest angle move
+     *
+     * Adjusts the angle of the headrest
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_ANGLE_MOVE = (
+        0x0B98
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Headrest fore/aft position
+     *
+     * Adjusts the headrest forwards and backwards.
+     * Max value indicates position closest to front of car.
+     * Min value indicates position closest to rear of car.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_FORE_AFT_POS = (
+        0x0B99
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Headrest fore/aft move
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    SEAT_HEADREST_FORE_AFT_MOVE = (
+        0x0B9A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:SEAT),
+
+    /*
+     * Window Position
+     *
+     * Max = window up / closed
+     * Min = window down / open
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_POS = (
+        0x0BC0
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Window Move
+     *
+     * Max = window up / closed
+     * Min = window down / open
+     * Magnitude denotes relative speed.  I.e. +2 is faster than +1 in raising
+     * the window.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_MOVE = (
+        0x0BC1
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Window Vent Position
+     *
+     * This feature is used to control the vent feature on a sunroof.
+     *
+     * Max = vent open
+     * Min = vent closed
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_VENT_POS = (
+        0x0BC2
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Window Vent Move
+     *
+     * This feature is used to control the vent feature on a sunroof.
+     *
+     * Max = vent open
+     * Min = vent closed
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_VENT_MOVE = (
+        0x0BC3
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Window Lock
+     *
+     * True indicates windows are locked and can't be moved.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    WINDOW_LOCK = (
+        0x0BC4
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /*
+     * Vehicle Maps Data Service (VMDS) message
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     */
+    VEHICLE_MAPS_DATA_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+
+    /*
+     * OBD2 Live Sensor Data
+     *
+     * This property uses COMPLEX data to send a snapshot of the current (live)
+     * values of the OBD2 sensors provided by the vehicle.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in Obd2IntegerSensorIndex are to be used to
+     * read from int32Values;
+     * the indices defined in Obd2FloatSensorIndex are to be used to
+     * read from floatValues.
+     *
+     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
+     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_LIVE_FRAME = (
+        0x0D00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+
+    /*
+     * OBD2 Freeze Frame Sensor Data
+     *
+     * This property uses COMPLEX data to send a snapshot of the values of the
+     * OBD2 sensors provided by the vehicle at the time that a diagnostic
+     * troubleshooting code (DTC) was recorded by the vehicle.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in Obd2IntegerSensorIndex are to be used to
+     * read from int32Values;
+     * the indices defined in Obd2FloatSensorIndex are to be used to
+     * read from floatValues;
+     * stringValue is the DTC that caused this freeze frame to be recorded.
+     *
+     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
+     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, and a possible
+     * valid stringValue is "P0176" to indicate a malfunction of the fuel
+     * composition sensor circuit.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     */
+    OBD2_FREEZE_FRAME = (
+        0x0D01
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+
+};
+
+/*
+ * Bit flags for fan direction
+ */
+enum VehicleHvacFanDirection : int32_t {
+  FACE = 0x1,
+  FLOOR = 0x2,
+  FACE_AND_FLOOR = 0x3,
+  DEFROST = 0x4,
+  DEFROST_AND_FLOOR = 0x5,
+};
+
+/*
+ * Constants relevant to radio.
+ */
+enum VehicleRadioConstants : int32_t {
+  /* Minimum value for the radio preset */
+  VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
+};
+
+enum VehicleAudioFocusRequest : int32_t {
+  REQUEST_GAIN = 0x1,
+  REQUEST_GAIN_TRANSIENT = 0x2,
+  REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
+  /*
+   * This is for the case where android side plays sound like UI feedback
+   * and car side does not need to duck existing playback as long as
+   * requested stream is available.
+   */
+  REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
+  REQUEST_RELEASE = 0x5,
+
+};
+
+enum VehicleAudioFocusState : int32_t {
+  /*
+   * Android side has permanent focus and can play allowed streams.
+   */
+  STATE_GAIN = 0x1,
+
+  /*
+   * Android side has transient focus and can play allowed streams.
+   */
+  STATE_GAIN_TRANSIENT = 0x2,
+
+  /*
+   * Car audio module is playing guidance kind of sound outside Android.
+   * Android side can still play through allowed streams with ducking.
+   */
+  STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
+
+  /*
+   * Car audio module is playing transient sound outside Android. Android side
+   * must stop playing any sounds.
+   */
+  STATE_LOSS_TRANSIENT = 0x4,
+
+  /*
+   * Android side has lost focus and cannot play any sound.
+   */
+  STATE_LOSS = 0x5,
+
+  /*
+   * car audio module is playing safety critical sound, and Android side cannot
+   * request focus until the current state is finished. car audio module
+   * restore it to the previous state when it can allow Android to play.
+   */
+  STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
+
+};
+
+/*
+ * Flags to represent multiple streams by combining these.
+ */
+enum VehicleAudioStreamFlag : int32_t {
+  STREAM0_FLAG = (0x1 << 0),
+  STREAM1_FLAG = (0x1 << 1),
+  STREAM2_FLAG = (0x1 << 2),
+};
+
+/*
+ * Represents stream number (always 0 to N -1 where N is max number of streams).
+ * Can be used for audio related property expecting one stream.
+ */
+enum VehicleAudioStream : int32_t {
+  STREAM0 = 0,
+  STREAM1 = 1,
+};
+
+/*
+ * Flag to represent external focus state (outside Android).
+ */
+enum VehicleAudioExtFocusFlag : int32_t {
+  /*
+   * No external focus holder.
+   */
+  NONE_FLAG = 0x0,
+
+  /*
+   * Car side (outside Android) has component holding GAIN kind of focus state.
+   */
+  PERMANENT_FLAG = 0x1,
+
+  /*
+   * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
+   * focus state.
+   */
+  TRANSIENT_FLAG = 0x2,
+
+  /*
+   * Car side is expected to play something while focus is held by Android side.
+   * One example can be radio attached in car side. But Android's radio app
+   * still must have focus, and Android side must be in GAIN state, but
+   * media stream will not be allocated to Android side and car side can play
+   * radio any time while this flag is active.
+   */
+  PLAY_ONLY_FLAG = 0x4,
+
+  /*
+   * Car side must mute any media including radio. This can be used with any
+   * focus request including GAIN* and RELEASE.
+   */
+  MUTE_MEDIA_FLAG = 0x8,
+};
+
+/*
+ * Index in int32Values for VehicleProperty#AUDIO_FOCUS property.
+ */
+enum VehicleAudioFocusIndex : int32_t {
+  FOCUS = 0,
+  STREAMS = 1,
+  EXTERNAL_FOCUS_STATE = 2,
+  AUDIO_CONTEXTS = 3,
+};
+
+/*
+ * Flags to tell the current audio context.
+ */
+enum VehicleAudioContextFlag : int32_t {
+  /* Music playback is currently active. */
+  MUSIC_FLAG = 0x1,
+
+  /* Navigation is currently running. */
+  NAVIGATION_FLAG = 0x2,
+
+  /* Voice command session is currently running. */
+  VOICE_COMMAND_FLAG = 0x4,
+
+  /* Voice call is currently active. */
+  CALL_FLAG = 0x8,
+
+  /*
+   * Alarm is active.
+   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+   */
+  ALARM_FLAG = 0x10,
+
+  /*
+   * Notification sound is active.
+   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+   */
+  NOTIFICATION_FLAG = 0x20,
+
+  /*
+   * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
+   * represent default stream for unknown contents.
+   */
+  UNKNOWN_FLAG = 0x40,
+
+  /* Safety alert / warning is played. */
+  SAFETY_ALERT_FLAG = 0x80,
+
+  /* CD / DVD kind of audio is played */
+  CD_ROM_FLAG = 0x100,
+
+  /* Aux audio input is played */
+  AUX_AUDIO_FLAG = 0x200,
+
+  /* system sound like UI feedback */
+  SYSTEM_SOUND_FLAG = 0x400,
+
+  /* Radio is played */
+  RADIO_FLAG = 0x800,
+
+  /* Ext source is played. This is for tagging generic ext sources. */
+  EXT_SOURCE_FLAG = 0x1000,
+};
+
+/*
+ * flags to represent capability of audio volume property.
+ * used in configArray[1] of VehiclePropConfig.
+ */
+enum VehicleAudioVolumeCapabilityFlag : int32_t {
+  /*
+   * External audio module or vehicle hal has persistent storage
+   * to keep the volume level. This must be set only when per context
+   * volume level is supported. When this is set, audio volume level per
+   * each context will be retrieved from the property when system starts up.
+   * And external audio module is also expected to adjust volume automatically
+   * whenever there is an audio context change.
+   * When this flag is not set, android side will assume that there is no
+   * persistent storage and stored value in android side will be used to
+   * initialize the volume level. And android side will set volume level
+   * of each physical streams whenever there is an audio context change.
+   */
+  PERSISTENT_STORAGE = 0x1,
+
+  /*
+   * When this flag is set, the H/W can support only single master volume for
+   * all streams.
+   * There is no way to set volume level differently per each stream or context.
+   */
+  MASTER_VOLUME_ONLY = 0x2,
+};
+
+/*
+ * enum to represent audio volume state.
+ */
+enum VehicleAudioVolumeState : int32_t {
+  STATE_OK = 0,
+
+  /*
+   * Audio volume has reached volume limit set in
+   * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
+   * further is not allowed.
+   */
+  LIMIT_REACHED = 1,
+};
+
+/*
+ * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
+ */
+enum VehicleAudioVolumeIndex : int32_t {
+  INDEX_STREAM = 0,
+  INDEX_VOLUME = 1,
+  INDEX_STATE = 2,
+};
+
+/*
+ * Index in int32Values for VehicleProperty#AUDIO_VOLUME_LIMIT property.
+ */
+enum VehicleAudioVolumeLimitIndex : int32_t {
+  STREAM = 0,
+  MAX_VOLUME = 1,
+};
+
+/*
+ * Index in int32Values for VehicleProperty#AUDIO_ROUTING_POLICY property.
+ */
+enum VehicleAudioRoutingPolicyIndex : int32_t {
+  STREAM = 0,
+  CONTEXTS = 1,
+};
+
+/*
+ * Flag to be used in VehiclePropConfig#configFlags for
+ * VehicleProperty#AUDIO_HW_VARIANT.
+ */
+enum VehicleAudioHwVariantConfigFlag : int32_t {
+  /*
+   * Flag to tell that radio is internal to android and radio must
+   * be treated like other android stream like media.
+   * When this flag is not set or AUDIO_HW_VARIANT does not exist,
+   * radio is treated as external module. This brins some delta in audio focus
+   * handling as well.
+   */
+  INTERNAL_RADIO_FLAG = 0x1,
+};
+
+enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
+  /*
+   * AP can enter deep sleep state. If not set, AP will always shutdown from
+   * VehicleApPowerState#SHUTDOWN_PREPARE power state.
+   */
+  ENABLE_DEEP_SLEEP_FLAG = 0x1,
+
+  /*
+   * The power controller can power on AP from off state after timeout
+   * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+   */
+  CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+};
+
+enum VehicleApPowerState : int32_t /* NOTE: type is guessed */ {
+  /* vehicle HAL will never publish this state to AP */
+  OFF = 0,
+
+  /* vehicle HAL will never publish this state to AP */
+  DEEP_SLEEP = 1,
+
+  /* AP is on but display must be off. */
+  ON_DISP_OFF = 2,
+
+  /* AP is on with display on. This state allows full user interaction. */
+  ON_FULL = 3,
+
+  /*
+   * The power controller has requested AP to shutdown. AP can either enter
+   * sleep state or start full shutdown. AP can also request postponing
+   * shutdown by sending VehicleApPowerSetState#SHUTDOWN_POSTPONE message. The
+   * power controller must change power state to this state to shutdown
+   * system.
+   *
+   * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+   */
+  SHUTDOWN_PREPARE = 4,
+};
+
+enum VehicleApPowerStateShutdownParam : int32_t {
+  /* AP must shutdown immediately. Postponing is not allowed. */
+  SHUTDOWN_IMMEDIATELY = 1,
+
+  /* AP can enter deep sleep instead of shutting down completely. */
+  CAN_SLEEP = 2,
+
+  /* AP can only shutdown with postponing allowed. */
+  SHUTDOWN_ONLY = 3,
+};
+
+enum VehicleApPowerSetState : int32_t /* NOTE: type is guessed */ {
+  /*
+   * AP has finished boot up, and can start shutdown if requested by power
+   * controller.
+   */
+  BOOT_COMPLETE = 0x1,
+
+  /*
+   * AP is entering deep sleep state. How this state is implemented may vary
+   * depending on each H/W, but AP's power must be kept in this state.
+   */
+  DEEP_SLEEP_ENTRY = 0x2,
+
+  /*
+   * AP is exiting from deep sleep state, and is in
+   * VehicleApPowerState#SHUTDOWN_PREPARE state.
+   * The power controller may change state to other ON states based on the
+   * current state.
+   */
+  DEEP_SLEEP_EXIT = 0x3,
+
+  /*
+   * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
+   *                 5000 ms.
+   *                 If AP needs more time, it will send another POSTPONE
+   *                 message before the previous one expires.
+   */
+  SHUTDOWN_POSTPONE = 0x4,
+
+  /*
+   * AP is starting shutting down. When system completes shutdown, everything
+   * will stop in AP as kernel will stop all other contexts. It is
+   * responsibility of vehicle HAL or lower level to synchronize that state
+   * with external power controller. As an example, some kind of ping
+   * with timeout in power controller can be a solution.
+   *
+   * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
+   *                 AP after specified time so that AP can run tasks like
+   *                 update. If it is set to 0, there is no wake up, and power
+   *                 controller may not necessarily support wake-up. If power
+   *                 controller turns on AP due to timer, it must start with
+   *                 VehicleApPowerState#ON_DISP_OFF state, and after
+   *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
+   *                 do state transition to
+   *                 VehicleApPowerState#SHUTDOWN_PREPARE.
+   */
+  SHUTDOWN_START = 0x5,
+
+  /*
+   * User has requested to turn off headunit's display, which is detected in
+   * android side.
+   * The power controller may change the power state to
+   * VehicleApPowerState#ON_DISP_OFF.
+   */
+  DISPLAY_OFF = 0x6,
+
+  /*
+   * User has requested to turn on headunit's display, most probably from power
+   * key input which is attached to headunit. The power controller may change
+   * the power state to VehicleApPowerState#ON_FULL.
+   */
+  DISPLAY_ON = 0x7,
+};
+
+/*
+ * Index in int32Values for VehicleProperty#AP_POWER_STATE property.
+ */
+enum VehicleApPowerStateIndex : int32_t {
+  STATE = 0,
+  ADDITIONAL = 1,
+};
+
+/*
+ * Enum to represent bootup reason.
+ */
+enum VehicleApPowerBootupReason : int32_t {
+  /*
+   * Power on due to user's pressing of power key or rotating of ignition
+   * switch.
+   */
+  USER_POWER_ON = 0,
+
+  /*
+   * Automatic power on triggered by door unlock or any other kind of automatic
+   * user detection.
+   */
+  USER_UNLOCK = 1,
+
+  /*
+   * Automatic power on triggered by timer. This only happens when AP has asked
+   * wake-up after
+   * certain time through time specified in
+   * VehicleApPowerSetState#SHUTDOWN_START.
+   */
+  TIMER = 2,
+};
+
+enum VehicleHwKeyInputAction : int32_t {
+  /* Key down */
+  ACTION_DOWN = 0,
+
+  /* Key up */
+  ACTION_UP = 1,
+};
+
+enum VehicleDisplay : int32_t {
+  /* center console */
+  MAIN = 0,
+
+  INSTRUMENT_CLUSTER = 1,
+};
+
+/*
+ * 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 {
+    SHOULD_NOT_USE = 0x000,
+
+    METER_PER_SEC  = 0x01,
+    RPM            = 0x02,
+    HERTZ          = 0x03,
+    PERCENTILE     = 0x10,
+    MILLIMETER     = 0x20,
+    METER          = 0x21,
+    KILOMETER      = 0x23,
+    CELSIUS        = 0x30,
+    FAHRENHEIT     = 0x31,
+    KELVIN         = 0x32,
+    MILLILITER     = 0x40,
+    NANO_SECS      = 0x50,
+    SECS           = 0x53,
+    YEAR           = 0x59,
+};
+
+  /*
+   * This describes how value of property can change.
+   */
+enum VehiclePropertyChangeMode : int32_t {
+  /*
+   * Property of this type must never be changed. Subscription is not supported
+   * for these properties.
+   */
+  STATIC = 0x00,
+
+  /*
+   * Property of this type must be reported when there is a change.
+   * IVehicle#get call must return the current value.
+   * Set operation for this property is assumed to be asynchronous. When the
+   * property is read (using IVehicle#get) after IVehicle#set, it may still
+   * return old value until underlying H/W backing this property has actually
+   * changed the state. Once state is changed, the property must dispatch
+   * changed value as event.
+   */
+  ON_CHANGE = 0x01,
+
+  /*
+   * Property of this type change continuously and requires fixed rate of
+   * sampling to retrieve the data.
+   */
+  CONTINUOUS = 0x02,
+
+  /*
+   * Property of this type may be polled to get the current value.
+   */
+  POLL = 0x03,
+
+  /*
+   * This is for property where change event must be sent only when the
+   * value is set from external component. Normal value change must not trigger
+   * event. For example, clock property can send change event only when it is
+   * set, outside android, for case like user setting time or time getting
+   * update. There is no need to send it per every value change.
+   */
+  ON_SET = 0x04,
+};
+
+/*
+ * Property config defines the capabilities of it. User of the API
+ * must first get the property config to understand the output from get()
+ * commands and also to ensure that set() or events commands are in sync with
+ * the expected output.
+ */
+enum VehiclePropertyAccess : int32_t {
+  NONE = 0x00,
+
+  READ = 0x01,
+  WRITE = 0x02,
+  READ_WRITE = 0x03,
+};
+
+/*
+ * Car states.
+ *
+ * The driving states determine what features of the UI will be accessible.
+ */
+enum VehicleDrivingStatus : int32_t {
+  UNRESTRICTED = 0x00,
+  NO_VIDEO = 0x01,
+  NO_KEYBOARD_INPUT = 0x02,
+  NO_VOICE_INPUT = 0x04,
+  NO_CONFIG = 0x08,
+  LIMIT_MESSAGE_LEN = 0x10,
+};
+
+/*
+ * Various gears which can be selected by user and chosen in system.
+ */
+enum VehicleGear: int32_t {
+  GEAR_NEUTRAL = 0x0001,
+  GEAR_REVERSE = 0x0002,
+  GEAR_PARK = 0x0004,
+  GEAR_DRIVE = 0x0008,
+  GEAR_LOW = 0x0010,
+  GEAR_1 = 0x0010,
+  GEAR_2 = 0x0020,
+  GEAR_3 = 0x0040,
+  GEAR_4 = 0x0080,
+  GEAR_5 = 0x0100,
+  GEAR_6 = 0x0200,
+  GEAR_7 = 0x0400,
+  GEAR_8 = 0x0800,
+  GEAR_9 = 0x1000,
+};
+
+/*
+ * Various zones in the car.
+ *
+ * Zones are used for Air Conditioning purposes and divide the car into physical
+ * area zones.
+ */
+enum VehicleAreaZone : int32_t {
+  ROW_1_LEFT = 0x00000001,
+  ROW_1_CENTER = 0x00000002,
+  ROW_1_RIGHT = 0x00000004,
+  ROW_1 = 0x00000008,
+  ROW_2_LEFT = 0x00000010,
+  ROW_2_CENTER = 0x00000020,
+  ROW_2_RIGHT = 0x00000040,
+  ROW_2 = 0x00000080,
+  ROW_3_LEFT = 0x00000100,
+  ROW_3_CENTER = 0x00000200,
+  ROW_3_RIGHT = 0x00000400,
+  ROW_3 = 0x00000800,
+  ROW_4_LEFT = 0x00001000,
+  ROW_4_CENTER = 0x00002000,
+  ROW_4_RIGHT = 0x00004000,
+  ROW_4 = 0x00008000,
+  WHOLE_CABIN = 0x80000000,
+};
+
+/*
+ * Various Seats in the car.
+ */
+enum VehicleAreaSeat : int32_t {
+    ROW_1_LEFT   = 0x0001,
+    ROW_1_CENTER = 0x0002,
+    ROW_1_RIGHT  = 0x0004,
+    ROW_2_LEFT   = 0x0010,
+    ROW_2_CENTER = 0x0020,
+    ROW_2_RIGHT  = 0x0040,
+    ROW_3_LEFT   = 0x0100,
+    ROW_3_CENTER = 0x0200,
+    ROW_3_RIGHT  = 0x0400
+};
+
+/*
+ * Various windshields/windows in the car.
+ */
+enum VehicleAreaWindow : int32_t {
+    FRONT_WINDSHIELD = 0x0001,
+    REAR_WINDSHIELD = 0x0002,
+    ROOF_TOP = 0x0004,
+    ROW_1_LEFT = 0x0010,
+    ROW_1_RIGHT = 0x0020,
+    ROW_2_LEFT = 0x0100,
+    ROW_2_RIGHT = 0x0200,
+    ROW_3_LEFT = 0x1000,
+    ROW_3_RIGHT = 0x2000,
+};
+
+enum VehicleAreaDoor : int32_t {
+    ROW_1_LEFT = 0x00000001,
+    ROW_1_RIGHT = 0x00000004,
+    ROW_2_LEFT = 0x00000010,
+    ROW_2_RIGHT = 0x00000040,
+    ROW_3_LEFT = 0x00000100,
+    ROW_3_RIGHT = 0x00000400,
+    HOOD = 0x10000000,
+    REAR = 0x20000000,
+};
+
+enum VehicleAreaMirror : int32_t {
+    DRIVER_LEFT = 0x00000001,
+    DRIVER_RIGHT = 0x00000002,
+    DRIVER_CENTER = 0x00000004,
+};
+
+enum VehicleTurnSignal : int32_t {
+    NONE = 0x00,
+    RIGHT = 0x01,
+    LEFT = 0x02,
+    EMERGENCY = 0x04,
+};
+
+struct VehicleAreaConfig {
+    /*
+     * Area id is ignored for VehiclePropertyGroup:GLOBAL properties.
+     */
+    int32_t areaId;
+
+    int32_t minInt32Value;
+    int32_t maxInt32Value;
+
+    int64_t minInt64Value;
+    int64_t maxInt64Value;
+
+    float minFloatValue;
+    float maxFloatValue;
+};
+
+struct VehiclePropConfig {
+    VehicleProperty prop;
+
+    /*
+     * Defines if the property is read or write or both.
+     */
+    VehiclePropertyAccess access;
+
+    /*
+     * Defines the change mode of the property.
+     */
+    VehiclePropertyChangeMode changeMode;
+
+    /*
+     * Some of the properties may have associated areas (for example, some hvac
+     * properties are associated with VehicleAreaZone), in these
+     * cases the config may contain an ORed value for the associated areas.
+     */
+    int32_t supportedAreas;
+
+    /*
+     * Contains per-area configuration.
+     */
+    vec<VehicleAreaConfig> areaConfigs;
+
+    /*
+     * Configuration flags for this property.
+     *
+     * For example, it may store the number of presets that are stored by the
+     * radio module.
+     */
+    int32_t configFlags;
+
+    /* Contains additional configuration parameters */
+    vec<int32_t> configArray;
+
+    /*
+     * Some properties may require additional information passed over this
+     * string. Most properties do not need to set this.
+     */
+    string configString;
+
+    /*
+     * Min sample rate in Hz.
+     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+     */
+    float minSampleRate;
+
+    /*
+     * Must be defined for VehiclePropertyChangeMode::CONTINUOUS
+     * Max sample rate in Hz.
+     */
+    float maxSampleRate;
+};
+
+/*
+ * Encapsulates the property name and the associated value. It
+ * is used across various API calls to set values, get values or to register for
+ * events.
+ */
+struct VehiclePropValue {
+    /* Property identifier */
+    VehicleProperty prop;
+
+    /* Time is elapsed nanoseconds since boot */
+    int64_t timestamp;
+
+    /*
+     * Area type(s) for non-global property it must be one of the value from
+     * VehicleArea* enums or 0 for global properties.
+     */
+    int32_t areaId;
+
+    /*
+     * Contains value for a single property. Depending on property data type of
+     * this property (VehiclePropetyType) one field of this structure must be filled in.
+     */
+    struct RawValue {
+        /*
+         * This is used for properties of types VehiclePropertyType#INT
+         * and VehiclePropertyType#INT_VEC
+         */
+        vec<int32_t> int32Values;
+
+        /*
+         * This is used for properties of types VehiclePropertyType#FLOAT
+         * and VehiclePropertyType#FLOAT_VEC
+         */
+        vec<float> floatValues;
+
+        /* This is used for properties of type VehiclePropertyType#INT64 */
+        vec<int64_t> int64Values;
+
+        /* This is used for properties of type VehiclePropertyType#BYTES */
+        vec<uint8_t> bytes;
+
+        /* This is used for properties of type VehiclePropertyType#STRING */
+        string stringValue;
+    };
+
+    RawValue value;
+};
+
+enum VehicleIgnitionState : int32_t {
+    UNDEFINED = 0,
+
+    /* Steering wheel is locked */
+    LOCK = 1,
+
+     /*
+      * Steering wheel is not locked, engine and all accessories are OFF. If
+      * car can be in LOCK and OFF state at the same time than HAL must report
+      * LOCK state.
+      */
+    OFF,
+
+    /*
+     * Typically in this state accessories become available (e.g. radio).
+     * Instrument cluster and engine are turned off
+     */
+    ACC,
+
+    /*
+     * Ignition is in state ON. Accessories and instrument cluster available,
+     * engine might be running or ready to be started.
+     */
+    ON,
+
+    /* Typically in this state engine is starting (cranking). */
+    START
+};
+
+
+/*
+ * Represent the operation where the current error has happened.
+ */
+enum VehiclePropertyOperation : int32_t {
+    /*
+     * Generic error to this property which is not tied to any operation.
+     */
+    GENERIC = 0,
+
+    /*
+     * Error happened while handling property set.
+     */
+    SET = 1,
+
+    /*
+     * Error happened while handling property get.
+     */
+    GET = 2,
+
+    /*
+     * Error happened while handling property subscription.
+     */
+    SUBSCRIBE = 3,
+};
+
+
+enum SubscribeFlags : int32_t {
+  UNDEFINED = 0x0,
+
+  /*
+   * Subscribe to event that was originated in vehicle HAL
+   * (most likely this event came from the vehicle itself).
+   */
+  HAL_EVENT = 0x1,
+
+  /*
+   * Use this flag to subscribe on events when IVehicle#set(...) was called by
+   * vehicle HAL's client (e.g. Car Service).
+   */
+  SET_CALL = 0x2,
+
+  DEFAULT = HAL_EVENT,
+};
+
+/*
+ * Encapsulates information about subscription to vehicle property events.
+ */
+struct SubscribeOptions {
+  /* Property to subscribe */
+  VehicleProperty propId;
+
+  /*
+   * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
+   * to all areas.
+   */
+  int32_t vehicleAreas;
+
+  /*
+   * Sample rate in Hz.
+   *
+   * Must be provided for properties with
+   * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
+   * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
+   * for a given property.
+   * This value indicates how many updates per second client wants to receive.
+   */
+  float sampleRate;
+
+  /* Flags that indicate what kind of events listen to. */
+  SubscribeFlags flags;
+};
+
+/* Error codes used in vehicle HAL interface. */
+enum StatusCode : int32_t {
+  OK = 0,
+
+  /* Try again. */
+  TRY_AGAIN = 1,
+
+  /* Invalid argument provided. */
+  INVALID_ARG = 2,
+
+  /*
+   * This code must be returned when device that associated with the vehicle
+   * property is not available. For example, when client tries to set HVAC
+   * temperature when the whole HVAC unit is turned OFF.
+   */
+  NOT_AVAILABLE = 3,
+
+  /* Access denied */
+  ACCESS_DENIED = 4,
+
+  /* Something unexpected has happened in Vehicle HAL */
+  INTERNAL_ERROR = 5,
+};
+
+/* The status of a fuel system as described by the OBD2 specification. */
+enum FuelSystemStatus : int32_t {
+  OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+
+  CLOSED_LOOP = 2,
+
+  OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+
+  OPEN_SYSTEM_FAILURE = 8,
+
+  CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+};
+
+/* Defines which ignition monitors are available to be read. */
+enum IgnitionMonitorKind : int32_t {
+  SPARK = 0,
+
+  COMPRESSION = 1,
+};
+
+/* These ignition monitors are common to both SPARK and COMPRESSION. */
+enum CommonIgnitionMonitors : int32_t {
+  COMPONENTS_AVAILABLE = 0x1 << 0,
+  COMPONENTS_INCOMPLETE = 0x1 << 1,
+
+  FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+  FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+
+  MISFIRE_AVAILABLE = 0x1 << 4,
+  MISFIRE_INCOMPLETE = 0x1 << 5,
+};
+
+/* Ignition monitors available for SPARK vehicles. */
+enum SparkIgnitionMonitors : CommonIgnitionMonitors {
+  EGR_AVAILABLE = 0x1 << 6,
+  EGR_INCOMPLETE = 0x1 << 7,
+
+  OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+  OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+
+  OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+  OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+
+  AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+  AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+
+  SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+  SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+
+  EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+  EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+
+  HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+  HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+
+  CATALYST_AVAILABLE = 0x1 << 20,
+  CATALYST_INCOMPLETE = 0x1 << 21,
+};
+
+/* Ignition monitors only available for COMPRESSION vehicles. */
+enum CompressionIgnitionMonitors : CommonIgnitionMonitors {
+  EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+  EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+
+  PM_FILTER_AVAILABLE = 0x1 << 8,
+  PM_FILTER_INCOMPLETE = 0x1 << 9,
+
+  EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+  EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+
+  BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+  BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+
+  NOx_SCR__AVAILABLE = 0x1 << 14,
+  NOx_SCR_INCOMPLETE = 0x1 << 15,
+
+  NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+  NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+};
+
+enum SecondaryAirStatus : int32_t {
+  UPSTREAM = 1,
+
+  DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+
+  FROM_OUTSIDE_OR_OFF = 4,
+
+  PUMP_ON_FOR_DIAGNOSTICS = 8,
+};
+
+enum FuelType : int32_t {
+  NOT_AVAILABLE = 0,
+
+  GASOLINE = 1,
+
+  METHANOL = 2,
+
+  ETHANOL = 3,
+
+  DIESEL = 4,
+
+  LPG = 5,
+
+  CNG = 6,
+
+  PROPANE = 7,
+
+  ELECTRIC = 8,
+
+  BIFUEL_RUNNING_GASOLINE = 9,
+
+  BIFUEL_RUNNING_METHANOL = 10,
+
+  BIFUEL_RUNNING_ETHANOL = 11,
+
+  BIFUEL_RUNNING_LPG = 12,
+
+  BIFUEL_RUNNING_CNG = 13,
+
+  BIFUEL_RUNNING_PROPANE = 14,
+
+  BIFUEL_RUNNING_ELECTRIC = 15,
+
+  BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+
+  HYBRID_GASOLINE = 17,
+
+  HYBRID_ETHANOL = 18,
+
+  HYBRID_DIESEL = 19,
+
+  HYBRID_ELECTRIC = 20,
+
+  HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+
+  HYBRID_REGENERATIVE = 22,
+
+  BIFUEL_RUNNING_DIESEL = 23,
+};
+
+/*
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ */
+enum Obd2IntegerSensorIndex : int32_t {
+  /* refer to FuelSystemStatus for a description of this value. */
+  FUEL_SYSTEM_STATUS = 0,
+
+  MALFUNCTION_INDICATOR_LIGHT_ON = 1,
+
+  /* refer to IgnitionMonitorKind for a description of this value. */
+  IGNITION_MONITORS_SUPPORTED = 2,
+
+  /*
+   * The value of this sensor is a bitmask that specifies whether ignition-specific
+   * tests are available and whether they are complete. The semantics of the individual
+   * bits in this value are given by, respectively, SparkIgnitionMonitors and
+   * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+   */
+  IGNITION_SPECIFIC_MONITORS = 3,
+
+  INTAKE_AIR_TEMPERATURE = 4,
+
+  /* refer to SecondaryAirStatus for a description of this value. */
+  COMMANDED_SECONDARY_AIR_STATUS = 5,
+
+  NUM_OXYGEN_SENSORS_PRESENT = 6,
+
+  RUNTIME_SINCE_ENGINE_START = 7,
+
+  DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
+
+  WARMUPS_SINCE_CODES_CLEARED = 9,
+
+  DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
+
+  ABSOLUTE_BAROMETRIC_PRESSURE = 11,
+
+  CONTROL_MODULE_VOLTAGE = 12,
+
+  AMBIENT_AIR_TEMPERATURE = 13,
+
+  TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
+
+  TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
+
+  MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
+
+  MAX_OXYGEN_SENSOR_VOLTAGE = 17,
+
+  MAX_OXYGEN_SENSOR_CURRENT = 18,
+
+  MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
+
+  MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
+
+  /* refer to FuelType for a description of this value. */
+  FUEL_TYPE = 21,
+
+  FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
+
+  ENGINE_OIL_TEMPERATURE = 23,
+
+  DRIVER_DEMAND_PERCENT_TORQUE = 24,
+
+  ENGINE_ACTUAL_PERCENT_TORQUE = 25,
+
+  ENGINE_REFERENCE_PERCENT_TORQUE = 26,
+
+  ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
+
+  ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
+
+  LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
+
+  VENDOR_START_INDEX = LAST_SYSTEM_INDEX + 1,
+};
+
+/*
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ */
+enum Obd2FloatSensorIndex : int32_t {
+  CALCULATED_ENGINE_LOAD = 0,
+
+  ENGINE_COOLANT_TEMPERATURE = 1,
+
+  SHORT_TERM_FUEL_TRIM_BANK1 = 2,
+
+  LONG_TERM_FUEL_TRIM_BANK1 = 3,
+
+  SHORT_TERM_FUEL_TRIM_BANK2 = 4,
+
+  LONG_TERM_FUEL_TRIM_BANK2 = 5,
+
+  FUEL_PRESSURE = 6,
+
+  INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
+
+  ENGINE_RPM = 8,
+
+  VEHICLE_SPEED = 9,
+
+  TIMING_ADVANCE = 10,
+
+  MAF_AIR_FLOW_RATE = 11,
+
+  THROTTLE_POSITION = 12,
+
+  OXYGEN_SENSOR1_VOLTAGE = 13,
+
+  OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
+
+  OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
+
+  OXYGEN_SENSOR2_VOLTAGE = 16,
+
+  OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
+
+  OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
+
+  OXYGEN_SENSOR3_VOLTAGE = 19,
+
+  OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
+
+  OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
+
+  OXYGEN_SENSOR4_VOLTAGE = 22,
+
+  OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
+
+  OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
+
+  OXYGEN_SENSOR5_VOLTAGE = 25,
+
+  OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
+
+  OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
+
+  OXYGEN_SENSOR6_VOLTAGE = 28,
+
+  OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
+
+  OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
+
+  OXYGEN_SENSOR7_VOLTAGE = 31,
+
+  OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
+
+  OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
+
+  OXYGEN_SENSOR8_VOLTAGE = 34,
+
+  OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
+
+  OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
+
+  FUEL_RAIL_PRESSURE = 37,
+
+  FUEL_RAIL_GAUGE_PRESSURE = 38,
+
+  COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
+
+  EXHAUST_GAS_RECIRCULATION_ERROR = 40,
+
+  COMMANDED_EVAPORATIVE_PURGE = 41,
+
+  FUEL_TANK_LEVEL_INPUT = 42,
+
+  EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
+
+  CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
+
+  CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
+
+  CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
+
+  CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
+
+  ABSOLUTE_LOAD_VALUE = 48,
+
+  FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
+
+  RELATIVE_THROTTLE_POSITION = 50,
+
+  ABSOLUTE_THROTTLE_POSITION_B = 51,
+
+  ABSOLUTE_THROTTLE_POSITION_C = 52,
+
+  ACCELERATOR_PEDAL_POSITION_D = 53,
+
+  ACCELERATOR_PEDAL_POSITION_E = 54,
+
+  ACCELERATOR_PEDAL_POSITION_F = 55,
+
+  COMMANDED_THROTTLE_ACTUATOR = 56,
+
+  ETHANOL_FUEL_PERCENTAGE = 57,
+
+  ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
+
+  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
+
+  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
+
+  RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
+
+  HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
+
+  FUEL_INJECTION_TIMING = 69,
+
+  ENGINE_FUEL_RATE = 70,
+
+  LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
+
+  VENDOR_START_INDEX = LAST_SYSTEM_INDEX + 1,
+};
diff --git a/vehicle/2.0/vts/Android.mk b/vehicle/2.0/vts/Android.mk
new file mode 100644
index 0000000..31fa999
--- /dev/null
+++ b/vehicle/2.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(LOCAL_PATH)/functional/vts/testcases/hal/vehicle/hidl/Android.mk
\ No newline at end of file
diff --git a/vehicle/2.0/vts/Vehicle.vts b/vehicle/2.0/vts/Vehicle.vts
new file mode 100644
index 0000000..7fecfa9
--- /dev/null
+++ b/vehicle/2.0/vts/Vehicle.vts
@@ -0,0 +1,116 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "IVehicle"
+
+package: "android.hardware.vehicle"
+
+import: "android.hardware.vehicle@2.0::IVehicleCallback"
+import: "android.hardware.vehicle@2.0::types"
+
+interface: {
+    api: {
+        name: "getAllPropConfigs"
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropConfig"
+            }
+        }
+    }
+
+    api: {
+        name: "getPropConfigs"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        return_type_hidl: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropConfig"
+            }
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_ENUM
+                predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+            }
+        }
+    }
+
+    api: {
+        name: "get"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        return_type_hidl: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+        }
+    }
+
+    api: {
+        name: "set"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+        }
+    }
+
+    api: {
+        name: "subscribe"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "IVehicleCallback"
+            is_callback: true
+        }
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::vehicle::V2_0::SubscribeOptions"
+            }
+        }
+    }
+
+    api: {
+        name: "unsubscribe"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        arg: {
+            type: TYPE_HIDL_CALLBACK
+            predefined_type: "IVehicleCallback"
+            is_callback: true
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+        }
+    }
+
+    api: {
+        name: "debugDump"
+        return_type_hidl: {
+            type: TYPE_STRING
+        }
+    }
+
+}
diff --git a/vehicle/2.0/vts/VehicleCallback.vts b/vehicle/2.0/vts/VehicleCallback.vts
new file mode 100644
index 0000000..b5ee152
--- /dev/null
+++ b/vehicle/2.0/vts/VehicleCallback.vts
@@ -0,0 +1,45 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "IVehicleCallback"
+
+package: "android.hardware.vehicle"
+
+import: "android.hardware.vehicle@2.0::types"
+
+interface: {
+    api: {
+        name: "onPropertyEvent"
+        arg: {
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_STRUCT
+                predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+            }
+        }
+    }
+
+    api: {
+        name: "onPropertySet"
+        arg: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+        }
+    }
+
+    api: {
+        name: "onPropertySetError"
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::StatusCode"
+        }
+        arg: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+
+}
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/__init__.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/__init__.py
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/Android.mk b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/__init__.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/__init__.py
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/Android.mk b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/Android.mk
new file mode 100644
index 0000000..716a41c
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VehicleHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vehicle/hidl/host
+include test/vts/tools/build/Android.host_config.mk
\ No newline at end of file
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/AndroidTest.xml b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..16b7c29
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL Vehicle test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/vehicle/2.0/vts/Vehicle.vts->/data/local/tmp/spec/Vehicle.vts" />
+        <option name="push" value="spec/hardware/interfaces/vehicle/2.0/vts/VehicleCallback.vts->/data/local/tmp/spec/VehicleCallBack.vts" />
+        <option name="push" value="spec/hardware/interfaces/vehicle/2.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VehicleHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest" />
+    </test>
+</configuration>
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
new file mode 100644
index 0000000..8024be2
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/VehicleHidlTest.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python3.4
+#
+# 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.
+#
+
+import logging
+import time
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import const
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.profiling import profiling_utils
+
+
+class VehicleHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """A simple testcase for the VEHICLE HIDL HAL."""
+
+    def setUpClass(self):
+        """Creates a mirror and init vehicle hal."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        results = self.dut.shell.one.Execute("id -u system")
+        system_uid = results[const.STDOUT][0].strip()
+        logging.info("system_uid: %s", system_uid)
+
+        self.dut.hal.InitHidlHal(
+            target_type="vehicle",
+            target_basepaths=self.dut.libPaths,
+            target_version=2.0,
+            target_package="android.hardware.vehicle",
+            target_component_name="IVehicle",
+            hw_binder_service_name="Vehicle",
+            bits=64 if self.dut.is64Bit else 32)
+
+        self.vehicle = self.dut.hal.vehicle  # shortcut
+        self.vehicle.SetCallerUid(system_uid)
+        self.vtypes = self.dut.hal.vehicle.GetHidlTypeInterface("types")
+        logging.info("vehicle types: %s", self.vtypes)
+
+    def tearDownClass(self):
+        """Disables the profiling.
+
+        If profiling is enabled for the test, collect the profiling data
+        and disable profiling after the test is done.
+        """
+        if self.enable_profiling:
+            self.ProcessAndUploadTraceData()
+
+    def setUpTest(self):
+        if self.enable_profiling:
+            profiling_utils.EnableVTSProfiling(self.dut.shell.one)
+
+    def tearDownTest(self):
+        if self.enable_profiling:
+            profiling_trace_path = getattr(
+                self, self.VTS_PROFILING_TRACING_PATH, "")
+            self.ProcessTraceDataForTestCase(self.dut, profiling_trace_path)
+            profiling_utils.DisableVTSProfiling(self.dut.shell.one)
+
+    def testListProperties(self):
+        """Checks whether some PropConfigs are returned.
+
+        Verifies that call to getAllPropConfigs is not failing and
+        it returns at least 1 vehicle property config.
+        """
+        allConfigs = self.vehicle.getAllPropConfigs()
+        logging.info("all supported properties: %s", allConfigs)
+        asserts.assertLess(0, len(allConfigs))
+
+    def testMandatoryProperties(self):
+        """Verifies that all mandatory properties are supported."""
+        mandatoryProps = set([self.vtypes.DRIVING_STATUS])  # 1 property so far
+        logging.info(self.vtypes.DRIVING_STATUS)
+        allConfigs = self.dut.hal.vehicle.getAllPropConfigs()
+
+        for config in allConfigs:
+            mandatoryProps.discard(config['prop'])
+
+        asserts.assertEqual(0, len(mandatoryProps))
+
+    def getSupportInfo(self):
+        """Check whether OBD2_{LIVE|FREEZE}_FRAME is supported."""
+        isLiveSupported, isFreezeSupported = False, False
+        allConfigs = self.vehicle.getAllPropConfigs()
+        for config in allConfigs:
+            if config['prop'] == self.vtypes.OBD2_LIVE_FRAME:
+                isLiveSupported = True
+            elif config['prop'] == self.vtypes.OBD2_FREEZE_FRAME:
+                isFreezeSupported = True
+            if isLiveSupported and isFreezeSupported:
+                break
+        return isLiveSupported, isFreezeSupported
+
+    def testObd2SensorProperties(self):
+        """Test reading the live and freeze OBD2 frame properties.
+
+        OBD2 (On-Board Diagnostics 2) is the industry standard protocol
+        for retrieving diagnostic sensor information from vehicles.
+        """
+        def checkLiveFrameRead():
+            """Validates reading the OBD2_LIVE_FRAME (if available)."""
+            logging.info("checkLiveFrameRead no-op pass")
+
+        def checkFreezeFrameRead():
+            """Validates reading the OBD2_FREEZE_FRAME (if available)."""
+            logging.info("checkLiveFrameRead no-op pass")
+
+        isLiveSupported, isFreezeSupported = self.getSupportInfo()
+        logging.info("isLiveSupported = %s, isFreezeSupported = %s",
+                     isLiveSupported, isFreezeSupported)
+        if isLiveSupported:
+            checkLiveFrameRead()
+        if isFreezeSupported:
+            checkFreezeFrameRead()
+
+    def createVehiclePropValue(self, propId):
+        value = {
+            "int32Values" : [],
+            "floatValues" : [],
+            "int64Values" : [],
+            "bytes": [],
+            "stringValue": ""
+        }
+        propValue = {
+            "prop": propId,
+            "timestamp": 0,
+            "areaId": 0,
+            "value": value
+        }
+        return self.vtypes.Py2Pb("VehiclePropValue", propValue)
+
+    def testDrivingStatus(self):
+        """Checks that DRIVING_STATUS property returns correct result."""
+        request = self.createVehiclePropValue(self.vtypes.DRIVING_STATUS)
+        logging.info("Driving status request: %s", request)
+        response = self.vehicle.get(request)
+        logging.info("Driving status response: %s", response)
+        status = response[0]
+        asserts.assertEqual(self.vtypes.OK, status)
+        propValue = response[1]
+        assertEqual(1, len(propValue.value.int32Values))
+        drivingStatus = propValue.value.int32Values[0]
+
+        allStatuses = self.vtypes.UNRESTRICTED or self.vtypes.NO_VIDEO or
+            self.vtypes.NO_KEYBOARD_INPUT or self.vtypes.NO_VOICE_INPUT or
+            self.vtypes.NO_CONFIG or self.vtypes.LIMIT_MESSAGE_LEN
+
+        assertEqual(allStatuses, allStatuses or drivingStatus)
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/__init__.py b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vehicle/2.0/vts/functional/vts/testcases/hal/vehicle/hidl/host/__init__.py
diff --git a/vehicle/2.0/vts/types.vts b/vehicle/2.0/vts/types.vts
new file mode 100644
index 0000000..fa7d892
--- /dev/null
+++ b/vehicle/2.0/vts/types.vts
@@ -0,0 +1,2673 @@
+component_class: HAL_HIDL
+component_type_version: 2.0
+component_name: "types"
+
+package: "android.hardware.vehicle"
+
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropertyType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STRING"
+        scalar_value: {
+            int32_t: 1048576
+        }
+        enumerator: "BOOLEAN"
+        scalar_value: {
+            int32_t: 2097152
+        }
+        enumerator: "INT32"
+        scalar_value: {
+            int32_t: 4194304
+        }
+        enumerator: "INT32_VEC"
+        scalar_value: {
+            int32_t: 4259840
+        }
+        enumerator: "INT64"
+        scalar_value: {
+            int32_t: 5242880
+        }
+        enumerator: "FLOAT"
+        scalar_value: {
+            int32_t: 6291456
+        }
+        enumerator: "FLOAT_VEC"
+        scalar_value: {
+            int32_t: 6356992
+        }
+        enumerator: "BYTES"
+        scalar_value: {
+            int32_t: 7340032
+        }
+        enumerator: "COMPLEX"
+        scalar_value: {
+            int32_t: 14680064
+        }
+        enumerator: "MASK"
+        scalar_value: {
+            int32_t: 16711680
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleArea"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GLOBAL"
+        scalar_value: {
+            int32_t: 16777216
+        }
+        enumerator: "ZONE"
+        scalar_value: {
+            int32_t: 33554432
+        }
+        enumerator: "WINDOW"
+        scalar_value: {
+            int32_t: 50331648
+        }
+        enumerator: "MIRROR"
+        scalar_value: {
+            int32_t: 67108864
+        }
+        enumerator: "SEAT"
+        scalar_value: {
+            int32_t: 83886080
+        }
+        enumerator: "DOOR"
+        scalar_value: {
+            int32_t: 100663296
+        }
+        enumerator: "MASK"
+        scalar_value: {
+            int32_t: 251658240
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropertyGroup"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SYSTEM"
+        scalar_value: {
+            int32_t: 268435456
+        }
+        enumerator: "VENDOR"
+        scalar_value: {
+            int32_t: 536870912
+        }
+        enumerator: "MASK"
+        scalar_value: {
+            int32_t: -268435456
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleProperty"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INVALID"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INFO_VIN"
+        scalar_value: {
+            int32_t: 286261504
+        }
+        enumerator: "INFO_MAKE"
+        scalar_value: {
+            int32_t: 286261505
+        }
+        enumerator: "INFO_MODEL"
+        scalar_value: {
+            int32_t: 286261506
+        }
+        enumerator: "INFO_MODEL_YEAR"
+        scalar_value: {
+            int32_t: 289407235
+        }
+        enumerator: "INFO_FUEL_CAPACITY"
+        scalar_value: {
+            int32_t: 291504388
+        }
+        enumerator: "PERF_ODOMETER"
+        scalar_value: {
+            int32_t: 291504644
+        }
+        enumerator: "PERF_VEHICLE_SPEED"
+        scalar_value: {
+            int32_t: 291504647
+        }
+        enumerator: "ENGINE_COOLANT_TEMP"
+        scalar_value: {
+            int32_t: 291504897
+        }
+        enumerator: "ENGINE_OIL_TEMP"
+        scalar_value: {
+            int32_t: 291504900
+        }
+        enumerator: "ENGINE_RPM"
+        scalar_value: {
+            int32_t: 291504901
+        }
+        enumerator: "GEAR_SELECTION"
+        scalar_value: {
+            int32_t: 289408000
+        }
+        enumerator: "CURRENT_GEAR"
+        scalar_value: {
+            int32_t: 289408001
+        }
+        enumerator: "PARKING_BRAKE_ON"
+        scalar_value: {
+            int32_t: 287310850
+        }
+        enumerator: "DRIVING_STATUS"
+        scalar_value: {
+            int32_t: 289408004
+        }
+        enumerator: "FUEL_LEVEL_LOW"
+        scalar_value: {
+            int32_t: 287310853
+        }
+        enumerator: "NIGHT_MODE"
+        scalar_value: {
+            int32_t: 287310855
+        }
+        enumerator: "TURN_SIGNAL_STATE"
+        scalar_value: {
+            int32_t: 289408008
+        }
+        enumerator: "IGNITION_STATE"
+        scalar_value: {
+            int32_t: 289408009
+        }
+        enumerator: "HVAC_FAN_SPEED"
+        scalar_value: {
+            int32_t: 306185472
+        }
+        enumerator: "HVAC_FAN_DIRECTION"
+        scalar_value: {
+            int32_t: 306185473
+        }
+        enumerator: "HVAC_TEMPERATURE_CURRENT"
+        scalar_value: {
+            int32_t: 308282626
+        }
+        enumerator: "HVAC_TEMPERATURE_SET"
+        scalar_value: {
+            int32_t: 308282627
+        }
+        enumerator: "HVAC_DEFROSTER"
+        scalar_value: {
+            int32_t: 320865540
+        }
+        enumerator: "HVAC_AC_ON"
+        scalar_value: {
+            int32_t: 304088325
+        }
+        enumerator: "HVAC_MAX_AC_ON"
+        scalar_value: {
+            int32_t: 304088326
+        }
+        enumerator: "HVAC_MAX_DEFROST_ON"
+        scalar_value: {
+            int32_t: 304088327
+        }
+        enumerator: "HVAC_RECIRC_ON"
+        scalar_value: {
+            int32_t: 304088328
+        }
+        enumerator: "HVAC_DUAL_ON"
+        scalar_value: {
+            int32_t: 304088329
+        }
+        enumerator: "HVAC_AUTO_ON"
+        scalar_value: {
+            int32_t: 304088330
+        }
+        enumerator: "HVAC_SEAT_TEMPERATURE"
+        scalar_value: {
+            int32_t: 356517131
+        }
+        enumerator: "HVAC_SIDE_MIRROR_HEAT"
+        scalar_value: {
+            int32_t: 339739916
+        }
+        enumerator: "HVAC_STEERING_WHEEL_TEMP"
+        scalar_value: {
+            int32_t: 289408269
+        }
+        enumerator: "HVAC_TEMPERATURE_UNITS"
+        scalar_value: {
+            int32_t: 306185486
+        }
+        enumerator: "HVAC_ACTUAL_FAN_SPEED_RPM"
+        scalar_value: {
+            int32_t: 306185487
+        }
+        enumerator: "HVAC_FAN_DIRECTION_AVAILABLE"
+        scalar_value: {
+            int32_t: 306185489
+        }
+        enumerator: "HVAC_POWER_ON"
+        scalar_value: {
+            int32_t: 304088336
+        }
+        enumerator: "ENV_OUTSIDE_TEMPERATURE"
+        scalar_value: {
+            int32_t: 291505923
+        }
+        enumerator: "ENV_CABIN_TEMPERATURE"
+        scalar_value: {
+            int32_t: 291505924
+        }
+        enumerator: "RADIO_PRESET"
+        scalar_value: {
+            int32_t: 289474561
+        }
+        enumerator: "AUDIO_FOCUS"
+        scalar_value: {
+            int32_t: 289474816
+        }
+        enumerator: "AUDIO_VOLUME"
+        scalar_value: {
+            int32_t: 289474817
+        }
+        enumerator: "AUDIO_VOLUME_LIMIT"
+        scalar_value: {
+            int32_t: 289474818
+        }
+        enumerator: "AUDIO_ROUTING_POLICY"
+        scalar_value: {
+            int32_t: 289474819
+        }
+        enumerator: "AUDIO_HW_VARIANT"
+        scalar_value: {
+            int32_t: 289409284
+        }
+        enumerator: "AUDIO_EXT_ROUTING_HINT"
+        scalar_value: {
+            int32_t: 289474821
+        }
+        enumerator: "AP_POWER_STATE"
+        scalar_value: {
+            int32_t: 2560
+        }
+        enumerator: "DISPLAY_BRIGHTNESS"
+        scalar_value: {
+            int32_t: 289409537
+        }
+        enumerator: "AP_POWER_BOOTUP_REASON"
+        scalar_value: {
+            int32_t: 289409538
+        }
+        enumerator: "HW_KEY_INPUT"
+        scalar_value: {
+            int32_t: 289475088
+        }
+        enumerator: "INSTRUMENT_CLUSTER_INFO"
+        scalar_value: {
+            int32_t: 289475104
+        }
+        enumerator: "UNIX_TIME"
+        scalar_value: {
+            int32_t: 290458160
+        }
+        enumerator: "CURRENT_TIME_IN_SECONDS"
+        scalar_value: {
+            int32_t: 289409585
+        }
+        enumerator: "DOOR_POS"
+        scalar_value: {
+            int32_t: 373295872
+        }
+        enumerator: "DOOR_MOVE"
+        scalar_value: {
+            int32_t: 373295873
+        }
+        enumerator: "DOOR_LOCK"
+        scalar_value: {
+            int32_t: 371198722
+        }
+        enumerator: "MIRROR_Z_POS"
+        scalar_value: {
+            int32_t: 339741504
+        }
+        enumerator: "MIRROR_Z_MOVE"
+        scalar_value: {
+            int32_t: 339741505
+        }
+        enumerator: "MIRROR_Y_POS"
+        scalar_value: {
+            int32_t: 339741506
+        }
+        enumerator: "MIRROR_Y_MOVE"
+        scalar_value: {
+            int32_t: 339741507
+        }
+        enumerator: "MIRROR_LOCK"
+        scalar_value: {
+            int32_t: 287312708
+        }
+        enumerator: "MIRROR_FOLD"
+        scalar_value: {
+            int32_t: 287312709
+        }
+        enumerator: "SEAT_MEMORY_SELECT"
+        scalar_value: {
+            int32_t: 356518784
+        }
+        enumerator: "SEAT_MEMORY_SET"
+        scalar_value: {
+            int32_t: 356518785
+        }
+        enumerator: "SEAT_BELT_BUCKLED"
+        scalar_value: {
+            int32_t: 354421634
+        }
+        enumerator: "SEAT_BELT_HEIGHT_POS"
+        scalar_value: {
+            int32_t: 356518787
+        }
+        enumerator: "SEAT_BELT_HEIGHT_MOVE"
+        scalar_value: {
+            int32_t: 356518788
+        }
+        enumerator: "SEAT_FORE_AFT_POS"
+        scalar_value: {
+            int32_t: 356518789
+        }
+        enumerator: "SEAT_FORE_AFT_MOVE"
+        scalar_value: {
+            int32_t: 356518790
+        }
+        enumerator: "SEAT_BACKREST_ANGLE_1_POS"
+        scalar_value: {
+            int32_t: 356518791
+        }
+        enumerator: "SEAT_BACKREST_ANGLE_1_MOVE"
+        scalar_value: {
+            int32_t: 356518792
+        }
+        enumerator: "SEAT_BACKREST_ANGLE_2_POS"
+        scalar_value: {
+            int32_t: 356518793
+        }
+        enumerator: "SEAT_BACKREST_ANGLE_2_MOVE"
+        scalar_value: {
+            int32_t: 356518794
+        }
+        enumerator: "SEAT_HEIGHT_POS"
+        scalar_value: {
+            int32_t: 356518795
+        }
+        enumerator: "SEAT_HEIGHT_MOVE"
+        scalar_value: {
+            int32_t: 356518796
+        }
+        enumerator: "SEAT_DEPTH_POS"
+        scalar_value: {
+            int32_t: 356518797
+        }
+        enumerator: "SEAT_DEPTH_MOVE"
+        scalar_value: {
+            int32_t: 356518798
+        }
+        enumerator: "SEAT_TILT_POS"
+        scalar_value: {
+            int32_t: 356518799
+        }
+        enumerator: "SEAT_TILT_MOVE"
+        scalar_value: {
+            int32_t: 356518800
+        }
+        enumerator: "SEAT_LUMBAR_FORE_AFT_POS"
+        scalar_value: {
+            int32_t: 356518801
+        }
+        enumerator: "SEAT_LUMBAR_FORE_AFT_MOVE"
+        scalar_value: {
+            int32_t: 356518802
+        }
+        enumerator: "SEAT_LUMBAR_SIDE_SUPPORT_POS"
+        scalar_value: {
+            int32_t: 356518803
+        }
+        enumerator: "SEAT_LUMBAR_SIDE_SUPPORT_MOVE"
+        scalar_value: {
+            int32_t: 356518804
+        }
+        enumerator: "SEAT_HEADREST_HEIGHT_POS"
+        scalar_value: {
+            int32_t: 289409941
+        }
+        enumerator: "SEAT_HEADREST_HEIGHT_MOVE"
+        scalar_value: {
+            int32_t: 356518806
+        }
+        enumerator: "SEAT_HEADREST_ANGLE_POS"
+        scalar_value: {
+            int32_t: 356518807
+        }
+        enumerator: "SEAT_HEADREST_ANGLE_MOVE"
+        scalar_value: {
+            int32_t: 356518808
+        }
+        enumerator: "SEAT_HEADREST_FORE_AFT_POS"
+        scalar_value: {
+            int32_t: 356518809
+        }
+        enumerator: "SEAT_HEADREST_FORE_AFT_MOVE"
+        scalar_value: {
+            int32_t: 356518810
+        }
+        enumerator: "WINDOW_POS"
+        scalar_value: {
+            int32_t: 289409984
+        }
+        enumerator: "WINDOW_MOVE"
+        scalar_value: {
+            int32_t: 289409985
+        }
+        enumerator: "WINDOW_VENT_POS"
+        scalar_value: {
+            int32_t: 289409986
+        }
+        enumerator: "WINDOW_VENT_MOVE"
+        scalar_value: {
+            int32_t: 289409987
+        }
+        enumerator: "WINDOW_LOCK"
+        scalar_value: {
+            int32_t: 287312836
+        }
+        enumerator: "VEHICLE_MAPS_DATA_SERVICE"
+        scalar_value: {
+            int32_t: 299895808
+        }
+        enumerator: "OBD2_LIVE_FRAME"
+        scalar_value: {
+            int32_t: 299896064
+        }
+        enumerator: "OBD2_FREEZE_FRAME"
+        scalar_value: {
+            int32_t: 299896065
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleHvacFanDirection"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FACE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "FLOOR"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FACE_AND_FLOOR"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "DEFROST"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "DEFROST_AND_FLOOR"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleRadioConstants"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "VEHICLE_RADIO_PRESET_MIN_VALUE"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioFocusRequest"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "REQUEST_GAIN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "REQUEST_GAIN_TRANSIENT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "REQUEST_GAIN_TRANSIENT_MAY_DUCK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "REQUEST_GAIN_TRANSIENT_NO_DUCK"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "REQUEST_RELEASE"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioFocusState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STATE_GAIN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "STATE_GAIN_TRANSIENT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "STATE_LOSS_TRANSIENT_CAN_DUCK"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "STATE_LOSS_TRANSIENT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "STATE_LOSS"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "STATE_LOSS_TRANSIENT_EXLCUSIVE"
+        scalar_value: {
+            int32_t: 6
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioStreamFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STREAM0_FLAG"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "STREAM1_FLAG"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "STREAM2_FLAG"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioStream"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STREAM0"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "STREAM1"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioExtFocusFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE_FLAG"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "PERMANENT_FLAG"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TRANSIENT_FLAG"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "PLAY_ONLY_FLAG"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "MUTE_MEDIA_FLAG"
+        scalar_value: {
+            int32_t: 8
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioFocusIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FOCUS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "STREAMS"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "EXTERNAL_FOCUS_STATE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "AUDIO_CONTEXTS"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioContextFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "MUSIC_FLAG"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NAVIGATION_FLAG"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "VOICE_COMMAND_FLAG"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "CALL_FLAG"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "ALARM_FLAG"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "NOTIFICATION_FLAG"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "UNKNOWN_FLAG"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "SAFETY_ALERT_FLAG"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "CD_ROM_FLAG"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "AUX_AUDIO_FLAG"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "SYSTEM_SOUND_FLAG"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "RADIO_FLAG"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "EXT_SOURCE_FLAG"
+        scalar_value: {
+            int32_t: 4096
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioVolumeCapabilityFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "PERSISTENT_STORAGE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "MASTER_VOLUME_ONLY"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioVolumeState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STATE_OK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "LIMIT_REACHED"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioVolumeIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INDEX_STREAM"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INDEX_VOLUME"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "INDEX_STATE"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioVolumeLimitIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STREAM"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MAX_VOLUME"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioRoutingPolicyIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STREAM"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "CONTEXTS"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAudioHwVariantConfigFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "INTERNAL_RADIO_FLAG"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerStateConfigFlag"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ENABLE_DEEP_SLEEP_FLAG"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CONFIG_SUPPORT_TIMER_POWER_ON_FLAG"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OFF"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "DEEP_SLEEP"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ON_DISP_OFF"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ON_FULL"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SHUTDOWN_PREPARE"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerStateShutdownParam"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SHUTDOWN_IMMEDIATELY"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CAN_SLEEP"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SHUTDOWN_ONLY"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerSetState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "BOOT_COMPLETE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DEEP_SLEEP_ENTRY"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "DEEP_SLEEP_EXIT"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SHUTDOWN_POSTPONE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "SHUTDOWN_START"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "DISPLAY_OFF"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "DISPLAY_ON"
+        scalar_value: {
+            int32_t: 7
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerStateIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STATE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ADDITIONAL"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleApPowerBootupReason"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "USER_POWER_ON"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "USER_UNLOCK"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "TIMER"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleHwKeyInputAction"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ACTION_DOWN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ACTION_UP"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleDisplay"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "MAIN"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "INSTRUMENT_CLUSTER"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleInstrumentClusterType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "HAL_INTERFACE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "EXTERNAL_DISPLAY"
+        scalar_value: {
+            int32_t: 2
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleUnit"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SHOULD_NOT_USE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "METER_PER_SEC"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "RPM"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "HERTZ"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "PERCENTILE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MILLIMETER"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "METER"
+        scalar_value: {
+            int32_t: 33
+        }
+        enumerator: "KILOMETER"
+        scalar_value: {
+            int32_t: 35
+        }
+        enumerator: "CELSIUS"
+        scalar_value: {
+            int32_t: 48
+        }
+        enumerator: "FAHRENHEIT"
+        scalar_value: {
+            int32_t: 49
+        }
+        enumerator: "KELVIN"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "MILLILITER"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "NANO_SECS"
+        scalar_value: {
+            int32_t: 80
+        }
+        enumerator: "SECS"
+        scalar_value: {
+            int32_t: 83
+        }
+        enumerator: "YEAR"
+        scalar_value: {
+            int32_t: 89
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropertyChangeMode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "STATIC"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ON_CHANGE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CONTINUOUS"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "POLL"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ON_SET"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropertyAccess"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "READ"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "WRITE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "READ_WRITE"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleDrivingStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNRESTRICTED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "NO_VIDEO"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "NO_KEYBOARD_INPUT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "NO_VOICE_INPUT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "NO_CONFIG"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "LIMIT_MESSAGE_LEN"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleGear"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GEAR_NEUTRAL"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "GEAR_REVERSE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "GEAR_PARK"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "GEAR_DRIVE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "GEAR_LOW"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "GEAR_1"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "GEAR_2"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "GEAR_3"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "GEAR_4"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "GEAR_5"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "GEAR_6"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "GEAR_7"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "GEAR_8"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "GEAR_9"
+        scalar_value: {
+            int32_t: 4096
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaZone"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ROW_1_LEFT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ROW_1_CENTER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ROW_1_RIGHT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ROW_1"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "ROW_2_LEFT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "ROW_2_CENTER"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "ROW_2_RIGHT"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "ROW_2"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "ROW_3_LEFT"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "ROW_3_CENTER"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "ROW_3_RIGHT"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "ROW_3"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "ROW_4_LEFT"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "ROW_4_CENTER"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "ROW_4_RIGHT"
+        scalar_value: {
+            int32_t: 16384
+        }
+        enumerator: "ROW_4"
+        scalar_value: {
+            int32_t: 32768
+        }
+        enumerator: "WHOLE_CABIN"
+        scalar_value: {
+            int32_t: -2147483648
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaSeat"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ROW_1_LEFT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ROW_1_CENTER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ROW_1_RIGHT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ROW_2_LEFT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "ROW_2_CENTER"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "ROW_2_RIGHT"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "ROW_3_LEFT"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "ROW_3_CENTER"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "ROW_3_RIGHT"
+        scalar_value: {
+            int32_t: 1024
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaWindow"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FRONT_WINDSHIELD"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "REAR_WINDSHIELD"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ROOF_TOP"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ROW_1_LEFT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "ROW_1_RIGHT"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "ROW_2_LEFT"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "ROW_2_RIGHT"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "ROW_3_LEFT"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "ROW_3_RIGHT"
+        scalar_value: {
+            int32_t: 8192
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaDoor"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "ROW_1_LEFT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "ROW_1_RIGHT"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "ROW_2_LEFT"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "ROW_2_RIGHT"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "ROW_3_LEFT"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "ROW_3_RIGHT"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "HOOD"
+        scalar_value: {
+            int32_t: 268435456
+        }
+        enumerator: "REAR"
+        scalar_value: {
+            int32_t: 536870912
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaMirror"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "DRIVER_LEFT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DRIVER_RIGHT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "DRIVER_CENTER"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleTurnSignal"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NONE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "RIGHT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "LEFT"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "EMERGENCY"
+        scalar_value: {
+            int32_t: 4
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleAreaConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "areaId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "minInt32Value"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "maxInt32Value"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "minInt64Value"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "maxInt64Value"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "minFloatValue"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "maxFloatValue"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropConfig"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "prop"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+    }
+    struct_value: {
+        name: "access"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropertyAccess"
+    }
+    struct_value: {
+        name: "changeMode"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropertyChangeMode"
+    }
+    struct_value: {
+        name: "supportedAreas"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "areaConfigs"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_STRUCT
+            predefined_type: "::android::hardware::vehicle::V2_0::VehicleAreaConfig"
+        }
+    }
+    struct_value: {
+        name: "configFlags"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "configArray"
+        type: TYPE_VECTOR
+        vector_value: {
+            type: TYPE_SCALAR
+            scalar_type: "int32_t"
+        }
+    }
+    struct_value: {
+        name: "configString"
+        type: TYPE_STRING
+    }
+    struct_value: {
+        name: "minSampleRate"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "maxSampleRate"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropValue"
+    type: TYPE_STRUCT
+    sub_struct: {
+        name: "::android::hardware::vehicle::V2_0::VehiclePropValue::RawValue"
+        type: TYPE_STRUCT
+        struct_value: {
+            name: "int32Values"
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "int32_t"
+            }
+        }
+        struct_value: {
+            name: "floatValues"
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "float_t"
+            }
+        }
+        struct_value: {
+            name: "int64Values"
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "int64_t"
+            }
+        }
+        struct_value: {
+            name: "bytes"
+            type: TYPE_VECTOR
+            vector_value: {
+                type: TYPE_SCALAR
+                scalar_type: "uint8_t"
+            }
+        }
+        struct_value: {
+            name: "stringValue"
+            type: TYPE_STRING
+        }
+    }
+    struct_value: {
+        name: "prop"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+    }
+    struct_value: {
+        name: "timestamp"
+        type: TYPE_SCALAR
+        scalar_type: "int64_t"
+    }
+    struct_value: {
+        name: "areaId"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "value"
+        type: TYPE_STRUCT
+        predefined_type: "::android::hardware::vehicle::V2_0::VehiclePropValue::RawValue"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehicleIgnitionState"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNDEFINED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "LOCK"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "OFF"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ACC"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ON"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "START"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::VehiclePropertyOperation"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "GENERIC"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "SET"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "GET"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "SUBSCRIBE"
+        scalar_value: {
+            int32_t: 3
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::SubscribeFlags"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UNDEFINED"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "HAL_EVENT"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SET_CALL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "DEFAULT"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::SubscribeOptions"
+    type: TYPE_STRUCT
+    struct_value: {
+        name: "propId"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::VehicleProperty"
+    }
+    struct_value: {
+        name: "vehicleAreas"
+        type: TYPE_SCALAR
+        scalar_type: "int32_t"
+    }
+    struct_value: {
+        name: "sampleRate"
+        type: TYPE_SCALAR
+        scalar_type: "float_t"
+    }
+    struct_value: {
+        name: "flags"
+        type: TYPE_ENUM
+        predefined_type: "::android::hardware::vehicle::V2_0::SubscribeFlags"
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::StatusCode"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "TRY_AGAIN"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "INVALID_ARG"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "ACCESS_DENIED"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "INTERNAL_ERROR"
+        scalar_value: {
+            int32_t: 5
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::FuelSystemStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "OPEN_INSUFFICIENT_ENGINE_TEMPERATURE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "CLOSED_LOOP"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "OPEN_ENGINE_LOAD_OR_DECELERATION"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "OPEN_SYSTEM_FAILURE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "CLOSED_LOOP_BUT_FEEDBACK_FAULT"
+        scalar_value: {
+            int32_t: 16
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::IgnitionMonitorKind"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "SPARK"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "COMPRESSION"
+        scalar_value: {
+            int32_t: 1
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::CommonIgnitionMonitors"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "COMPONENTS_AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "COMPONENTS_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FUEL_SYSTEM_AVAILABLE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "FUEL_SYSTEM_INCOMPLETE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "MISFIRE_AVAILABLE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MISFIRE_INCOMPLETE"
+        scalar_value: {
+            int32_t: 32
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::SparkIgnitionMonitors"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "COMPONENTS_AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "COMPONENTS_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FUEL_SYSTEM_AVAILABLE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "FUEL_SYSTEM_INCOMPLETE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "MISFIRE_AVAILABLE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MISFIRE_INCOMPLETE"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "EGR_AVAILABLE"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "EGR_INCOMPLETE"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "OXYGEN_SENSOR_HEATER_AVAILABLE"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "OXYGEN_SENSOR_HEATER_INCOMPLETE"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "OXYGEN_SENSOR_AVAILABLE"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "OXYGEN_SENSOR_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "AC_REFRIGERANT_AVAILABLE"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "AC_REFRIGERANT_INCOMPLETE"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "SECONDARY_AIR_SYSTEM_AVAILABLE"
+        scalar_value: {
+            int32_t: 16384
+        }
+        enumerator: "SECONDARY_AIR_SYSTEM_INCOMPLETE"
+        scalar_value: {
+            int32_t: 32768
+        }
+        enumerator: "EVAPORATIVE_SYSTEM_AVAILABLE"
+        scalar_value: {
+            int32_t: 65536
+        }
+        enumerator: "EVAPORATIVE_SYSTEM_INCOMPLETE"
+        scalar_value: {
+            int32_t: 131072
+        }
+        enumerator: "HEATED_CATALYST_AVAILABLE"
+        scalar_value: {
+            int32_t: 262144
+        }
+        enumerator: "HEATED_CATALYST_INCOMPLETE"
+        scalar_value: {
+            int32_t: 524288
+        }
+        enumerator: "CATALYST_AVAILABLE"
+        scalar_value: {
+            int32_t: 1048576
+        }
+        enumerator: "CATALYST_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2097152
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::CompressionIgnitionMonitors"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "COMPONENTS_AVAILABLE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "COMPONENTS_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FUEL_SYSTEM_AVAILABLE"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "FUEL_SYSTEM_INCOMPLETE"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "MISFIRE_AVAILABLE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MISFIRE_INCOMPLETE"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "EGR_OR_VVT_AVAILABLE"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "EGR_OR_VVT_INCOMPLETE"
+        scalar_value: {
+            int32_t: 128
+        }
+        enumerator: "PM_FILTER_AVAILABLE"
+        scalar_value: {
+            int32_t: 256
+        }
+        enumerator: "PM_FILTER_INCOMPLETE"
+        scalar_value: {
+            int32_t: 512
+        }
+        enumerator: "EXHAUST_GAS_SENSOR_AVAILABLE"
+        scalar_value: {
+            int32_t: 1024
+        }
+        enumerator: "EXHAUST_GAS_SENSOR_INCOMPLETE"
+        scalar_value: {
+            int32_t: 2048
+        }
+        enumerator: "BOOST_PRESSURE_AVAILABLE"
+        scalar_value: {
+            int32_t: 4096
+        }
+        enumerator: "BOOST_PRESSURE_INCOMPLETE"
+        scalar_value: {
+            int32_t: 8192
+        }
+        enumerator: "NOx_SCR__AVAILABLE"
+        scalar_value: {
+            int32_t: 16384
+        }
+        enumerator: "NOx_SCR_INCOMPLETE"
+        scalar_value: {
+            int32_t: 32768
+        }
+        enumerator: "NMHC_CATALYST_AVAILABLE"
+        scalar_value: {
+            int32_t: 65536
+        }
+        enumerator: "NMHC_CATALYST_INCOMPLETE"
+        scalar_value: {
+            int32_t: 131072
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::SecondaryAirStatus"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "UPSTREAM"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "DOWNSTREAM_OF_CATALYCIC_CONVERTER"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "FROM_OUTSIDE_OR_OFF"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "PUMP_ON_FOR_DIAGNOSTICS"
+        scalar_value: {
+            int32_t: 8
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::FuelType"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "NOT_AVAILABLE"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "GASOLINE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "METHANOL"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "ETHANOL"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "DIESEL"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "LPG"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "CNG"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "PROPANE"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "ELECTRIC"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "BIFUEL_RUNNING_GASOLINE"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "BIFUEL_RUNNING_METHANOL"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "BIFUEL_RUNNING_ETHANOL"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "BIFUEL_RUNNING_LPG"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "BIFUEL_RUNNING_CNG"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "BIFUEL_RUNNING_PROPANE"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "BIFUEL_RUNNING_ELECTRIC"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "HYBRID_GASOLINE"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "HYBRID_ETHANOL"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "HYBRID_DIESEL"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "HYBRID_ELECTRIC"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "HYBRID_REGENERATIVE"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "BIFUEL_RUNNING_DIESEL"
+        scalar_value: {
+            int32_t: 23
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::Obd2IntegerSensorIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "FUEL_SYSTEM_STATUS"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "MALFUNCTION_INDICATOR_LIGHT_ON"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "IGNITION_MONITORS_SUPPORTED"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "COMMANDED_SECONDARY_AIR_STATUS"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "NUM_OXYGEN_SENSORS_PRESENT"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "RUNTIME_SINCE_ENGINE_START"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "WARMUPS_SINCE_CODES_CLEARED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "DISTANCE_TRAVELED_SINCE_CODES_CLEARED"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "ABSOLUTE_BAROMETRIC_PRESSURE"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "CONTROL_MODULE_VOLTAGE"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "AMBIENT_AIR_TEMPERATURE"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "TIME_WITH_MALFUNCTION_LIGHT_ON"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "TIME_SINCE_TROUBLE_CODES_CLEARED"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "MAX_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "MAX_OXYGEN_SENSOR_VOLTAGE"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "MAX_OXYGEN_SENSOR_CURRENT"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "FUEL_TYPE"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "FUEL_RAIL_ABSOLUTE_PRESSURE"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "ENGINE_OIL_TEMPERATURE"
+        scalar_value: {
+            int32_t: 23
+        }
+        enumerator: "DRIVER_DEMAND_PERCENT_TORQUE"
+        scalar_value: {
+            int32_t: 24
+        }
+        enumerator: "ENGINE_ACTUAL_PERCENT_TORQUE"
+        scalar_value: {
+            int32_t: 25
+        }
+        enumerator: "ENGINE_REFERENCE_PERCENT_TORQUE"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "ENGINE_PERCENT_TORQUE_DATA_IDLE"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "ENGINE_PERCENT_TORQUE_DATA_POINT1"
+        scalar_value: {
+            int32_t: 28
+        }
+        enumerator: "ENGINE_PERCENT_TORQUE_DATA_POINT2"
+        scalar_value: {
+            int32_t: 29
+        }
+        enumerator: "ENGINE_PERCENT_TORQUE_DATA_POINT3"
+        scalar_value: {
+            int32_t: 30
+        }
+        enumerator: "ENGINE_PERCENT_TORQUE_DATA_POINT4"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "LAST_SYSTEM_INDEX"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "VENDOR_START_INDEX"
+        scalar_value: {
+            int32_t: 32
+        }
+    }
+}
+
+attribute: {
+    name: "::android::hardware::vehicle::V2_0::Obd2FloatSensorIndex"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "int32_t"
+
+        enumerator: "CALCULATED_ENGINE_LOAD"
+        scalar_value: {
+            int32_t: 0
+        }
+        enumerator: "ENGINE_COOLANT_TEMPERATURE"
+        scalar_value: {
+            int32_t: 1
+        }
+        enumerator: "SHORT_TERM_FUEL_TRIM_BANK1"
+        scalar_value: {
+            int32_t: 2
+        }
+        enumerator: "LONG_TERM_FUEL_TRIM_BANK1"
+        scalar_value: {
+            int32_t: 3
+        }
+        enumerator: "SHORT_TERM_FUEL_TRIM_BANK2"
+        scalar_value: {
+            int32_t: 4
+        }
+        enumerator: "LONG_TERM_FUEL_TRIM_BANK2"
+        scalar_value: {
+            int32_t: 5
+        }
+        enumerator: "FUEL_PRESSURE"
+        scalar_value: {
+            int32_t: 6
+        }
+        enumerator: "INTAKE_MANIFOLD_ABSOLUTE_PRESSURE"
+        scalar_value: {
+            int32_t: 7
+        }
+        enumerator: "ENGINE_RPM"
+        scalar_value: {
+            int32_t: 8
+        }
+        enumerator: "VEHICLE_SPEED"
+        scalar_value: {
+            int32_t: 9
+        }
+        enumerator: "TIMING_ADVANCE"
+        scalar_value: {
+            int32_t: 10
+        }
+        enumerator: "MAF_AIR_FLOW_RATE"
+        scalar_value: {
+            int32_t: 11
+        }
+        enumerator: "THROTTLE_POSITION"
+        scalar_value: {
+            int32_t: 12
+        }
+        enumerator: "OXYGEN_SENSOR1_VOLTAGE"
+        scalar_value: {
+            int32_t: 13
+        }
+        enumerator: "OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 14
+        }
+        enumerator: "OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 15
+        }
+        enumerator: "OXYGEN_SENSOR2_VOLTAGE"
+        scalar_value: {
+            int32_t: 16
+        }
+        enumerator: "OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 17
+        }
+        enumerator: "OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 18
+        }
+        enumerator: "OXYGEN_SENSOR3_VOLTAGE"
+        scalar_value: {
+            int32_t: 19
+        }
+        enumerator: "OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 20
+        }
+        enumerator: "OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 21
+        }
+        enumerator: "OXYGEN_SENSOR4_VOLTAGE"
+        scalar_value: {
+            int32_t: 22
+        }
+        enumerator: "OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 23
+        }
+        enumerator: "OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 24
+        }
+        enumerator: "OXYGEN_SENSOR5_VOLTAGE"
+        scalar_value: {
+            int32_t: 25
+        }
+        enumerator: "OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 26
+        }
+        enumerator: "OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 27
+        }
+        enumerator: "OXYGEN_SENSOR6_VOLTAGE"
+        scalar_value: {
+            int32_t: 28
+        }
+        enumerator: "OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 29
+        }
+        enumerator: "OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 30
+        }
+        enumerator: "OXYGEN_SENSOR7_VOLTAGE"
+        scalar_value: {
+            int32_t: 31
+        }
+        enumerator: "OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 32
+        }
+        enumerator: "OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 33
+        }
+        enumerator: "OXYGEN_SENSOR8_VOLTAGE"
+        scalar_value: {
+            int32_t: 34
+        }
+        enumerator: "OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM"
+        scalar_value: {
+            int32_t: 35
+        }
+        enumerator: "OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 36
+        }
+        enumerator: "FUEL_RAIL_PRESSURE"
+        scalar_value: {
+            int32_t: 37
+        }
+        enumerator: "FUEL_RAIL_GAUGE_PRESSURE"
+        scalar_value: {
+            int32_t: 38
+        }
+        enumerator: "COMMANDED_EXHAUST_GAS_RECIRCULATION"
+        scalar_value: {
+            int32_t: 39
+        }
+        enumerator: "EXHAUST_GAS_RECIRCULATION_ERROR"
+        scalar_value: {
+            int32_t: 40
+        }
+        enumerator: "COMMANDED_EVAPORATIVE_PURGE"
+        scalar_value: {
+            int32_t: 41
+        }
+        enumerator: "FUEL_TANK_LEVEL_INPUT"
+        scalar_value: {
+            int32_t: 42
+        }
+        enumerator: "EVAPORATION_SYSTEM_VAPOR_PRESSURE"
+        scalar_value: {
+            int32_t: 43
+        }
+        enumerator: "CATALYST_TEMPERATURE_BANK1_SENSOR1"
+        scalar_value: {
+            int32_t: 44
+        }
+        enumerator: "CATALYST_TEMPERATURE_BANK2_SENSOR1"
+        scalar_value: {
+            int32_t: 45
+        }
+        enumerator: "CATALYST_TEMPERATURE_BANK1_SENSOR2"
+        scalar_value: {
+            int32_t: 46
+        }
+        enumerator: "CATALYST_TEMPERATURE_BANK2_SENSOR2"
+        scalar_value: {
+            int32_t: 47
+        }
+        enumerator: "ABSOLUTE_LOAD_VALUE"
+        scalar_value: {
+            int32_t: 48
+        }
+        enumerator: "FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO"
+        scalar_value: {
+            int32_t: 49
+        }
+        enumerator: "RELATIVE_THROTTLE_POSITION"
+        scalar_value: {
+            int32_t: 50
+        }
+        enumerator: "ABSOLUTE_THROTTLE_POSITION_B"
+        scalar_value: {
+            int32_t: 51
+        }
+        enumerator: "ABSOLUTE_THROTTLE_POSITION_C"
+        scalar_value: {
+            int32_t: 52
+        }
+        enumerator: "ACCELERATOR_PEDAL_POSITION_D"
+        scalar_value: {
+            int32_t: 53
+        }
+        enumerator: "ACCELERATOR_PEDAL_POSITION_E"
+        scalar_value: {
+            int32_t: 54
+        }
+        enumerator: "ACCELERATOR_PEDAL_POSITION_F"
+        scalar_value: {
+            int32_t: 55
+        }
+        enumerator: "COMMANDED_THROTTLE_ACTUATOR"
+        scalar_value: {
+            int32_t: 56
+        }
+        enumerator: "ETHANOL_FUEL_PERCENTAGE"
+        scalar_value: {
+            int32_t: 57
+        }
+        enumerator: "ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE"
+        scalar_value: {
+            int32_t: 58
+        }
+        enumerator: "SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1"
+        scalar_value: {
+            int32_t: 59
+        }
+        enumerator: "SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2"
+        scalar_value: {
+            int32_t: 60
+        }
+        enumerator: "SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3"
+        scalar_value: {
+            int32_t: 61
+        }
+        enumerator: "SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4"
+        scalar_value: {
+            int32_t: 62
+        }
+        enumerator: "LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1"
+        scalar_value: {
+            int32_t: 63
+        }
+        enumerator: "LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2"
+        scalar_value: {
+            int32_t: 64
+        }
+        enumerator: "LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3"
+        scalar_value: {
+            int32_t: 65
+        }
+        enumerator: "LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4"
+        scalar_value: {
+            int32_t: 66
+        }
+        enumerator: "RELATIVE_ACCELERATOR_PEDAL_POSITION"
+        scalar_value: {
+            int32_t: 67
+        }
+        enumerator: "HYBRID_BATTERY_PACK_REMAINING_LIFE"
+        scalar_value: {
+            int32_t: 68
+        }
+        enumerator: "FUEL_INJECTION_TIMING"
+        scalar_value: {
+            int32_t: 69
+        }
+        enumerator: "ENGINE_FUEL_RATE"
+        scalar_value: {
+            int32_t: 70
+        }
+        enumerator: "LAST_SYSTEM_INDEX"
+        scalar_value: {
+            int32_t: 70
+        }
+        enumerator: "VENDOR_START_INDEX"
+        scalar_value: {
+            int32_t: 71
+        }
+    }
+}
+
diff --git a/vehicle/Android.bp b/vehicle/Android.bp
new file mode 100644
index 0000000..c12cd4f
--- /dev/null
+++ b/vehicle/Android.bp
@@ -0,0 +1,4 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "2.0",
+]
diff --git a/vibrator/1.0/Android.bp b/vibrator/1.0/Android.bp
new file mode 100644
index 0000000..497274b
--- /dev/null
+++ b/vibrator/1.0/Android.bp
@@ -0,0 +1,159 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.vibrator@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0",
+    srcs: [
+        "types.hal",
+        "IVibrator.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/types.cpp",
+        "android/hardware/vibrator/1.0/VibratorAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vibrator@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0",
+    srcs: [
+        "types.hal",
+        "IVibrator.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/types.h",
+        "android/hardware/vibrator/1.0/IVibrator.h",
+        "android/hardware/vibrator/1.0/IHwVibrator.h",
+        "android/hardware/vibrator/1.0/BnHwVibrator.h",
+        "android/hardware/vibrator/1.0/BpHwVibrator.h",
+        "android/hardware/vibrator/1.0/BsVibrator.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vibrator@1.0",
+    generated_sources: ["android.hardware.vibrator@1.0_genc++"],
+    generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vibrator.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/vibrator/1.0/ $(genDir)/android/hardware/vibrator/1.0/",
+    srcs: [
+        "types.hal",
+        "IVibrator.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/types.vts.cpp",
+        "android/hardware/vibrator/1.0/Vibrator.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vibrator.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/vibrator/1.0/ $(genDir)/android/hardware/vibrator/1.0/",
+    srcs: [
+        "types.hal",
+        "IVibrator.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/types.vts.h",
+        "android/hardware/vibrator/1.0/Vibrator.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vibrator.vts.driver@1.0",
+    generated_sources: ["android.hardware.vibrator.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.vibrator.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vibrator.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vibrator@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vibrator@1.0-IVibrator-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/vibrator/1.0/ $(genDir)/android/hardware/vibrator/1.0/",
+    srcs: [
+        "IVibrator.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/Vibrator.vts.cpp",
+        "android/hardware/vibrator/1.0/types.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vibrator@1.0-IVibrator-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vibrator@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/vibrator/1.0/ $(genDir)/android/hardware/vibrator/1.0/",
+    srcs: [
+        "IVibrator.hal",
+        "types.hal",
+    ],
+    out: [
+        "android/hardware/vibrator/1.0/Vibrator.vts.h",
+        "android/hardware/vibrator/1.0/types.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vibrator@1.0-IVibrator-vts.profiler",
+    generated_sources: ["android.hardware.vibrator@1.0-IVibrator-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.vibrator@1.0-IVibrator-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.vibrator@1.0-IVibrator-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vibrator@1.0",
+    ],
+}
diff --git a/vibrator/1.0/Android.mk b/vibrator/1.0/Android.mk
new file mode 100644
index 0000000..1437d44
--- /dev/null
+++ b/vibrator/1.0/Android.mk
@@ -0,0 +1,118 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vibrator@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVibrator.hal
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/IVibrator.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVibrator.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::IVibrator
+
+$(GEN): $(LOCAL_PATH)/IVibrator.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vibrator@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::types.Status
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IVibrator.hal
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/IVibrator.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVibrator.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::IVibrator
+
+$(GEN): $(LOCAL_PATH)/IVibrator.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/vibrator/1.0/IVibrator.hal b/vibrator/1.0/IVibrator.hal
new file mode 100644
index 0000000..0a4ffca
--- /dev/null
+++ b/vibrator/1.0/IVibrator.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vibrator@1.0;
+
+interface IVibrator {
+  /** Turn on vibrator
+   *
+   * This function must only be called after the previous timeout has expired or
+   * was canceled (through off()).
+   * @param timeout_ms number of milliseconds to vibrate.
+   * @return vibratorOnRet whether vibrator command was successful or not.
+   */
+  on(uint32_t timeoutMs) generates (Status vibratorOnRet);
+
+  /** Turn off vibrator
+   *
+   * Cancel a previously-started vibration, if any.
+   * @return vibratorOffRet whether vibrator command was successful or not.
+   */
+  off() generates (Status vibratorOffRet);
+};
diff --git a/vibrator/1.0/default/Android.bp b/vibrator/1.0/default/Android.bp
new file mode 100644
index 0000000..5e488e6
--- /dev/null
+++ b/vibrator/1.0/default/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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.vibrator@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Vibrator.cpp"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libhwbinder",
+        "libutils",
+        "libhardware",
+        "android.hardware.vibrator@1.0",
+    ],
+}
diff --git a/vibrator/1.0/default/Android.mk b/vibrator/1.0/default/Android.mk
new file mode 100644
index 0000000..5ba334b
--- /dev/null
+++ b/vibrator/1.0/default/Android.mk
@@ -0,0 +1,35 @@
+#
+# 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.
+
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vibrator@1.0-service
+LOCAL_INIT_RC := android.hardware.vibrator@1.0-service.rc
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_SRC_FILES := \
+  service.cpp \
+
+LOCAL_SHARED_LIBRARIES := \
+  libhidlbase \
+  libhidltransport \
+  liblog \
+  libhwbinder \
+  libutils \
+  libhardware \
+  android.hardware.vibrator@1.0
+
+include $(BUILD_EXECUTABLE)
diff --git a/vibrator/1.0/default/Vibrator.cpp b/vibrator/1.0/default/Vibrator.cpp
new file mode 100644
index 0000000..8c82bcd
--- /dev/null
+++ b/vibrator/1.0/default/Vibrator.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VibratorService"
+
+#include <log/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/vibrator.h>
+
+#include "Vibrator.h"
+
+namespace android {
+namespace hardware {
+namespace vibrator {
+namespace V1_0 {
+namespace implementation {
+
+Vibrator::Vibrator(vibrator_device_t *device) : mDevice(device) {}
+
+// Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
+Return<Status> Vibrator::on(uint32_t timeout_ms) {
+    int32_t ret = mDevice->vibrator_on(mDevice, timeout_ms);
+    if (ret != 0) {
+        ALOGE("on command failed : %s", strerror(-ret));
+        return Status::ERR;
+    }
+    return Status::OK;
+}
+
+Return<Status> Vibrator::off()  {
+    int32_t ret = mDevice->vibrator_off(mDevice);
+    if (ret != 0) {
+        ALOGE("off command failed : %s", strerror(-ret));
+        return Status::ERR;
+    }
+    return Status::OK;
+}
+
+IVibrator* HIDL_FETCH_IVibrator(const char * /*hal*/) {
+    vibrator_device_t *vib_device;
+    const hw_module_t *hw_module = nullptr;
+
+    int ret = hw_get_module(VIBRATOR_HARDWARE_MODULE_ID, &hw_module);
+    if (ret == 0) {
+        ret = vibrator_open(hw_module, &vib_device);
+        if (ret != 0) {
+            ALOGE("vibrator_open failed: %d", ret);
+        }
+    } else {
+        ALOGE("hw_get_module %s failed: %d", VIBRATOR_HARDWARE_MODULE_ID, ret);
+    }
+
+    if (ret == 0) {
+        return new Vibrator(vib_device);
+    } else {
+        ALOGE("Passthrough failed to open legacy HAL.");
+        return nullptr;
+    }
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace vibrator
+}  // namespace hardware
+}  // namespace android
diff --git a/vibrator/1.0/default/Vibrator.h b/vibrator/1.0/default/Vibrator.h
new file mode 100644
index 0000000..061b364
--- /dev/null
+++ b/vibrator/1.0/default/Vibrator.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_VIBRATOR_V1_0_VIBRATOR_H
+#define ANDROID_HARDWARE_VIBRATOR_V1_0_VIBRATOR_H
+
+#include <android/hardware/vibrator/1.0/IVibrator.h>
+#include <hidl/Status.h>
+
+#include <hidl/MQDescriptor.h>
+namespace android {
+namespace hardware {
+namespace vibrator {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::vibrator::V1_0::IVibrator;
+using ::android::hardware::vibrator::V1_0::Status;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+
+struct Vibrator : public IVibrator {
+  Vibrator(vibrator_device_t *device);
+
+  // Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
+  Return<Status> on(uint32_t timeoutMs)  override;
+  Return<Status> off()  override;
+
+  private:
+    vibrator_device_t    *mDevice;
+};
+
+extern "C" IVibrator* HIDL_FETCH_IVibrator(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace vibrator
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_VIBRATOR_V1_0_VIBRATOR_H
diff --git a/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
new file mode 100644
index 0000000..a7836b3
--- /dev/null
+++ b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
@@ -0,0 +1,4 @@
+service vibrator-1-0 /system/bin/hw/android.hardware.vibrator@1.0-service
+    class hal
+    user system
+    group system readproc
diff --git a/vibrator/1.0/default/service.cpp b/vibrator/1.0/default/service.cpp
new file mode 100644
index 0000000..064e1e2
--- /dev/null
+++ b/vibrator/1.0/default/service.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.vibrator@1.0-service"
+
+#include <android/hardware/vibrator/1.0/IVibrator.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::vibrator::V1_0::IVibrator;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IVibrator>("vibrator");
+}
diff --git a/vibrator/1.0/types.hal b/vibrator/1.0/types.hal
new file mode 100644
index 0000000..8fc5683
--- /dev/null
+++ b/vibrator/1.0/types.hal
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vibrator@1.0;
+
+enum Status: uint32_t {
+    OK             = 0,
+    ERR            = 1
+};
diff --git a/vibrator/1.0/vts/Android.mk b/vibrator/1.0/vts/Android.mk
new file mode 100644
index 0000000..df5dac8
--- /dev/null
+++ b/vibrator/1.0/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
\ No newline at end of file
diff --git a/vibrator/1.0/vts/Vibrator.vts b/vibrator/1.0/vts/Vibrator.vts
new file mode 100644
index 0000000..e0de3fb
--- /dev/null
+++ b/vibrator/1.0/vts/Vibrator.vts
@@ -0,0 +1,30 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IVibrator"
+
+package: "android.hardware.vibrator"
+
+import: "android.hardware.vibrator@1.0::types"
+
+interface: {
+    api: {
+        name: "on"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vibrator::V1_0::Status"
+        }
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "uint32_t"
+        }
+    }
+
+    api: {
+        name: "off"
+        return_type_hidl: {
+            type: TYPE_ENUM
+            predefined_type: "::android::hardware::vibrator::V1_0::Status"
+        }
+    }
+
+}
diff --git a/vibrator/1.0/vts/functional/Android.bp b/vibrator/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..a24cf5c
--- /dev/null
+++ b/vibrator/1.0/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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_test {
+    name: "vibrator_hidl_hal_test",
+    gtest: true,
+    srcs: ["vibrator_hidl_hal_test.cpp"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "libutils",
+        "android.hardware.vibrator@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
+
diff --git a/vibrator/1.0/vts/functional/Android.mk b/vibrator/1.0/vts/functional/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp b/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp
new file mode 100644
index 0000000..782a763
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vibrator_hidl_hal_test.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "vibrator_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/vibrator/1.0/IVibrator.h>
+#include <android/hardware/vibrator/1.0/types.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+
+using ::android::hardware::vibrator::V1_0::IVibrator;
+using ::android::hardware::vibrator::V1_0::Status;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+// The main test class for VIBRATOR HIDL HAL.
+class VibratorHidlTest : public ::testing::Test {
+ public:
+  virtual void SetUp() override {
+    vibrator = IVibrator::getService(false);
+    ASSERT_NE(vibrator, nullptr);
+  }
+
+  virtual void TearDown() override {}
+
+  sp<IVibrator> vibrator;
+};
+
+// A class for test environment setup (kept since this file is a template).
+class VibratorHidlEnvironment : public ::testing::Environment {
+ public:
+  virtual void SetUp() {}
+  virtual void TearDown() {}
+
+ private:
+};
+
+TEST_F(VibratorHidlTest, OnThenOffBeforeTimeout) {
+  EXPECT_EQ(Status::OK, vibrator->on(2000));
+  sleep(1);
+  EXPECT_EQ(Status::OK, vibrator->off());
+}
+
+int main(int argc, char **argv) {
+  ::testing::AddGlobalTestEnvironment(new VibratorHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
diff --git a/vibrator/1.0/vts/functional/vts/Android.mk b/vibrator/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vts/testcases/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/__init__.py b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/__init__.py
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/__init__.py b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/__init__.py
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/Android.mk
new file mode 100644
index 0000000..d005450
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VibratorHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vibrator/hidl/host
+include test/vts/tools/build/Android.host_config.mk
\ No newline at end of file
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/AndroidTest.xml b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..c5074ee
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL vibrator test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/vibrator/1.0/vts/Vibrator.vts->/data/local/tmp/spec/Vibrator.vts" />
+        <option name="push" value="spec/hardware/interfaces/vibrator/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VibratorHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest" />
+    </test>
+</configuration>
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py
new file mode 100644
index 0000000..84f2907
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3.4
+#
+# 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.
+#
+
+import logging
+import time
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.profiling import profiling_utils
+
+
+class VibratorHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """A simple testcase for the VIBRATOR HIDL HAL."""
+
+    def setUpClass(self):
+        """Creates a mirror and turns on the framework-layer VIBRATOR service."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        # Test using the binderized mode
+        self.dut.shell.one.Execute(
+            "setprop vts.hal.vts.hidl.get_stub true")
+
+        self.dut.hal.InitHidlHal(
+            target_type="vibrator",
+            target_basepaths=self.dut.libPaths,
+            target_version=1.0,
+            target_package="android.hardware.vibrator",
+            target_component_name="IVibrator",
+            bits=64 if self.dut.is64Bit else 32)
+
+    def tearDownClass(self):
+        """ If profiling is enabled for the test, collect the profiling data
+            and disable profiling after the test is done.
+        """
+        if self.enable_profiling:
+            self.ProcessAndUploadTraceData()
+
+    def setUpTest(self):
+        if self.enable_profiling:
+            profiling_utils.EnableVTSProfiling(self.dut.shell.one)
+
+    def tearDownTest(self):
+        if self.enable_profiling:
+            profiling_trace_path = getattr(
+                self, self.VTS_PROFILING_TRACING_PATH, "")
+            self.ProcessTraceDataForTestCase(self.dut, profiling_trace_path)
+            profiling_utils.DisableVTSProfiling(self.dut.shell.one)
+
+    def testVibratorBasic(self):
+        """A simple test case which just calls each registered function."""
+        vibrator_types = self.dut.hal.vibrator.GetHidlTypeInterface("types")
+        logging.info("vibrator_types: %s", vibrator_types)
+        logging.info("OK: %s", vibrator_types.OK)
+        logging.info("ERR: %s", vibrator_types.ERR)
+
+        result = self.dut.hal.vibrator.on(10000)
+        logging.info("on result: %s", result)
+        asserts.assertEqual(vibrator_types.OK, result)
+
+        time.sleep(1)
+
+        result = self.dut.hal.vibrator.off()
+        logging.info("off result: %s", result)
+        asserts.assertEqual(vibrator_types.OK, result)
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/__init__.py b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host/__init__.py
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/Android.mk
new file mode 100644
index 0000000..ec73e06
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VibratorHidlProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vibrator/hidl/host_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/AndroidTest.xml b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/AndroidTest.xml
new file mode 100644
index 0000000..54830f0
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/host_profiling/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL vibrator test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/vibrator/1.0/vts/Vibrator.vts->/data/local/tmp/spec/Vibrator.vts" />
+        <option name="push" value="spec/hardware/interfaces/vibrator/1.0/vts/types.vts->/data/local/tmp/spec/types.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VibratorHidlProfilingTest" />
+        <option name="test-case-path" value="vts/testcases/hal/vibrator/hidl/host/VibratorHidlTest" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/Android.mk
new file mode 100644
index 0000000..704d985
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VibratorHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vibrator/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/AndroidTest.xml b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..7948c86
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VIBRATOR HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VibratorHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/vibrator_hidl_hal_test/vibrator_hidl_hal_test,
+            _64bit::DATA/nativetest64/vibrator_hidl_hal_test/vibrator_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+    </test>
+</configuration>
+
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/Android.mk b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..a1f43e4
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VibratorHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vibrator/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/AndroidTest.xml b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..4643e23
--- /dev/null
+++ b/vibrator/1.0/vts/functional/vts/testcases/hal/vibrator/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VIBRATOR HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VibratorHidlTargetProfilingTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/vibrator_hidl_hal_test/vibrator_hidl_hal_test,
+            _64bit::DATA/nativetest64/vibrator_hidl_hal_test/vibrator_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
+
diff --git a/vibrator/1.0/vts/types.vts b/vibrator/1.0/vts/types.vts
new file mode 100644
index 0000000..d1bf1e1
--- /dev/null
+++ b/vibrator/1.0/vts/types.vts
@@ -0,0 +1,24 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "types"
+
+package: "android.hardware.vibrator"
+
+
+attribute: {
+    name: "::android::hardware::vibrator::V1_0::Status"
+    type: TYPE_ENUM
+    enum_value: {
+        scalar_type: "uint32_t"
+
+        enumerator: "OK"
+        scalar_value: {
+            uint32_t: 0
+        }
+        enumerator: "ERR"
+        scalar_value: {
+            uint32_t: 1
+        }
+    }
+}
+
diff --git a/vibrator/Android.bp b/vibrator/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/vibrator/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]
diff --git a/vr/1.0/Android.bp b/vr/1.0/Android.bp
new file mode 100644
index 0000000..f175610
--- /dev/null
+++ b/vr/1.0/Android.bp
@@ -0,0 +1,147 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+genrule {
+    name: "android.hardware.vr@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/VrAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vr@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/IVr.h",
+        "android/hardware/vr/1.0/IHwVr.h",
+        "android/hardware/vr/1.0/BnHwVr.h",
+        "android/hardware/vr/1.0/BpHwVr.h",
+        "android/hardware/vr/1.0/BsVr.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vr@1.0",
+    generated_sources: ["android.hardware.vr@1.0_genc++"],
+    generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vr.vts.driver@1.0_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0 && $(location vtsc) -mDRIVER -tSOURCE -b$(genDir) android/hardware/vr/1.0/ $(genDir)/android/hardware/vr/1.0/",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/Vr.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vr.vts.driver@1.0_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0 && $(location vtsc) -mDRIVER -tHEADER -b$(genDir) android/hardware/vr/1.0/ $(genDir)/android/hardware/vr/1.0/",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/Vr.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vr.vts.driver@1.0",
+    generated_sources: ["android.hardware.vr.vts.driver@1.0_genc++"],
+    generated_headers: ["android.hardware.vr.vts.driver@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.vr.vts.driver@1.0_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "libvts_common",
+        "libvts_datatype",
+        "libvts_measurement",
+        "libvts_multidevice_proto",
+        "libcamera_metadata",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vr@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hidl.base@1.0",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vr@1.0-IVr-vts.profiler_genc++",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0 && $(location vtsc) -mPROFILER -tSOURCE -b$(genDir) android/hardware/vr/1.0/ $(genDir)/android/hardware/vr/1.0/",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/Vr.vts.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.vr@1.0-IVr-vts.profiler_genc++_headers",
+    tools: ["hidl-gen", "vtsc"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lvts -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.vr@1.0 && $(location vtsc) -mPROFILER -tHEADER -b$(genDir) android/hardware/vr/1.0/ $(genDir)/android/hardware/vr/1.0/",
+    srcs: [
+        "IVr.hal",
+    ],
+    out: [
+        "android/hardware/vr/1.0/Vr.vts.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.vr@1.0-IVr-vts.profiler",
+    generated_sources: ["android.hardware.vr@1.0-IVr-vts.profiler_genc++"],
+    generated_headers: ["android.hardware.vr@1.0-IVr-vts.profiler_genc++_headers"],
+    export_generated_headers: ["android.hardware.vr@1.0-IVr-vts.profiler_genc++_headers"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libvts_profiling",
+        "libvts_multidevice_proto",
+        "libprotobuf-cpp-full",
+        "android.hidl.base@1.0",
+        "android.hardware.vr@1.0",
+    ],
+}
diff --git a/vr/1.0/Android.mk b/vr/1.0/Android.mk
new file mode 100644
index 0000000..1b8e8c7
--- /dev/null
+++ b/vr/1.0/Android.mk
@@ -0,0 +1,76 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vr@1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build IVr.hal
+#
+GEN := $(intermediates)/android/hardware/vr/V1_0/IVr.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVr.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vr@1.0::IVr
+
+$(GEN): $(LOCAL_PATH)/IVr.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vr@1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build IVr.hal
+#
+GEN := $(intermediates)/android/hardware/vr/V1_0/IVr.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVr.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vr@1.0::IVr
+
+$(GEN): $(LOCAL_PATH)/IVr.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/vr/1.0/IVr.hal b/vr/1.0/IVr.hal
new file mode 100644
index 0000000..1f996e9
--- /dev/null
+++ b/vr/1.0/IVr.hal
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.hardware.vr@1.0;
+
+interface IVr {
+  /**
+   * Convenience method to set up any state needed at runtime startup.  This is
+   * called once from the VrManagerService during its boot phase.
+   */
+  @callflow(next={"*"})
+  @entry
+  @exit
+  init();
+
+  /**
+   * Set the VR mode state.  Possible states of the enabled parameter are:
+   * false - VR mode is disabled, turn off all VR-specific settings.
+   * true - VR mode is enabled, turn on all VR-specific settings.
+   *
+   * This must be called whenever the the Android system enters or leaves VR
+   * mode. This will typically occur when the user switches to or from a VR
+   * application that is doing stereoscopic rendering.
+   */
+  @callflow(next={"*"})
+  @exit
+  setVrMode(bool enabled);
+};
diff --git a/vr/1.0/default/Android.bp b/vr/1.0/default/Android.bp
new file mode 100644
index 0000000..d100570
--- /dev/null
+++ b/vr/1.0/default/Android.bp
@@ -0,0 +1,17 @@
+cc_library_shared {
+    name: "android.hardware.vr@1.0-impl",
+    relative_install_path: "hw",
+    srcs: ["Vr.cpp"],
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libhardware",
+        "libhwbinder",
+        "libbase",
+        "libcutils",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.vr@1.0",
+    ],
+}
diff --git a/vr/1.0/default/Vr.cpp b/vr/1.0/default/Vr.cpp
new file mode 100644
index 0000000..a0de998
--- /dev/null
+++ b/vr/1.0/default/Vr.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VrService"
+
+#include <log/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/vr.h>
+
+#include "Vr.h"
+
+namespace android {
+namespace hardware {
+namespace vr {
+namespace V1_0 {
+namespace implementation {
+
+Vr::Vr(vr_module_t *device) : mDevice(device) {}
+
+// Methods from ::android::hardware::vr::V1_0::IVr follow.
+Return<void> Vr::init() {
+    mDevice->init(mDevice);
+    return Void();
+}
+
+Return<void> Vr::setVrMode(bool enabled)  {
+    mDevice->set_vr_mode(mDevice, enabled);
+    return Void();
+}
+
+IVr* HIDL_FETCH_IVr(const char *name) {
+    vr_module_t *vr_module;
+    const hw_module_t *hw_module = NULL;
+
+    int ret = hw_get_module(name, &hw_module);
+    if (ret == 0) {
+        return new Vr(reinterpret_cast<vr_module_t*>(
+                const_cast<hw_module_t*>(hw_module)));
+    } else {
+        ALOGE("hw_get_module %s failed: %d", name, ret);
+        return nullptr;
+    }
+}
+
+} // namespace implementation
+}  // namespace V1_0
+}  // namespace vr
+}  // namespace hardware
+}  // namespace android
diff --git a/vr/1.0/default/Vr.h b/vr/1.0/default/Vr.h
new file mode 100644
index 0000000..dd5e764
--- /dev/null
+++ b/vr/1.0/default/Vr.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_VR_V1_0_VR_H
+#define ANDROID_HARDWARE_VR_V1_0_VR_H
+
+#include <android/hardware/vr/1.0/IVr.h>
+#include <hardware/vr.h>
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace vr {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::vr::V1_0::IVr;
+using ::android::hardware::Return;
+
+struct Vr : public IVr {
+    Vr(vr_module_t *device);
+
+    // Methods from ::android::hardware::vr::V1_0::IVr follow.
+    Return<void> init()  override;
+    Return<void> setVrMode(bool enabled)  override;
+
+  private:
+    vr_module_t    *mDevice;
+};
+
+extern "C" IVr* HIDL_FETCH_IVr(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace vr
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_VR_V1_0_VR_H
diff --git a/vr/1.0/default/android.hardware.vr@1.0-service.rc b/vr/1.0/default/android.hardware.vr@1.0-service.rc
new file mode 100644
index 0000000..6177089
--- /dev/null
+++ b/vr/1.0/default/android.hardware.vr@1.0-service.rc
@@ -0,0 +1,4 @@
+service vr-1-0 /system/bin/hw/android.hardware.vr@1.0-service
+    class hal
+    user system
+    group system readproc
diff --git a/vr/1.0/default/service.cpp b/vr/1.0/default/service.cpp
new file mode 100644
index 0000000..c27ceaf
--- /dev/null
+++ b/vr/1.0/default/service.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.vr@1.0-service"
+
+#include <android/hardware/vr/1.0/IVr.h>
+#include <hidl/LegacySupport.h>
+
+// Generated HIDL files
+using android::hardware::vr::V1_0::IVr;
+using android::hardware::defaultPassthroughServiceImplementation;
+
+int main() {
+    return defaultPassthroughServiceImplementation<IVr>("vr");
+}
diff --git a/vr/1.0/vts/Android.mk b/vr/1.0/vts/Android.mk
new file mode 100644
index 0000000..e8afa86
--- /dev/null
+++ b/vr/1.0/vts/Android.mk
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+# include hidl test makefiles
+include $(LOCAL_PATH)/functional/vts/testcases/hal/vr/hidl/Android.mk
diff --git a/vr/1.0/vts/Vr.vts b/vr/1.0/vts/Vr.vts
new file mode 100644
index 0000000..36ec11f
--- /dev/null
+++ b/vr/1.0/vts/Vr.vts
@@ -0,0 +1,36 @@
+component_class: HAL_HIDL
+component_type_version: 1.0
+component_name: "IVr"
+
+package: "android.hardware.vr"
+
+
+interface: {
+    api: {
+        name: "init"
+        callflow: {
+            next: "*"
+        }
+        callflow: {
+            entry: true
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+    api: {
+        name: "setVrMode"
+        arg: {
+            type: TYPE_SCALAR
+            scalar_type: "bool_t"
+        }
+        callflow: {
+            next: "*"
+        }
+        callflow: {
+            exit: true
+        }
+    }
+
+}
diff --git a/vr/1.0/vts/functional/Android.bp b/vr/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..551f27c
--- /dev/null
+++ b/vr/1.0/vts/functional/Android.bp
@@ -0,0 +1,36 @@
+//
+// 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_test {
+    name: "vr_hidl_hal_test",
+    gtest: true,
+    srcs: ["vr_hidl_hal_test.cpp"],
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libutils",
+        "android.hardware.vr@1.0",
+    ],
+    static_libs: ["libgtest"],
+    cflags: [
+       "--coverage",
+       "-O0",
+        "-g",
+    ],
+    ldflags: [
+        "--coverage"
+    ]
+}
diff --git a/vr/1.0/vts/functional/vr_hidl_hal_test.cpp b/vr/1.0/vts/functional/vr_hidl_hal_test.cpp
new file mode 100644
index 0000000..85ecbdc
--- /dev/null
+++ b/vr/1.0/vts/functional/vr_hidl_hal_test.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "vr_hidl_hal_test"
+#include <android-base/logging.h>
+#include <android/hardware/vr/1.0/IVr.h>
+#include <android/log.h>
+#include <gtest/gtest.h>
+#include <hardware/vr.h>
+
+using ::android::hardware::vr::V1_0::IVr;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+#define VR_SERVICE_NAME "vr"
+
+// The main test class for VR HIDL HAL.
+class VrHidlTest : public ::testing::Test {
+ public:
+  void SetUp() override {
+    // currently test passthrough mode only
+    vr = IVr::getService(VR_SERVICE_NAME, true);
+    ASSERT_NE(vr, nullptr);
+    ASSERT_TRUE(!vr->isRemote());
+  }
+
+  void TearDown() override {}
+
+  sp<IVr> vr;
+};
+
+
+// A class for test environment setup (kept since this file is a template).
+class VrHidlEnvironment : public ::testing::Environment {
+ public:
+  void SetUp() {}
+  void TearDown() {}
+
+ private:
+};
+
+// Sanity check that Vr::init does not crash.
+TEST_F(VrHidlTest, Init) {
+  EXPECT_TRUE(vr->init().isOk());
+}
+
+// Sanity check Vr::setVrMode is able to enable and disable VR mode.
+TEST_F(VrHidlTest, SetVrMode) {
+  EXPECT_TRUE(vr->init().isOk());
+  EXPECT_TRUE(vr->setVrMode(true).isOk());
+  EXPECT_TRUE(vr->setVrMode(false).isOk());
+}
+
+// Sanity check that Vr::init and Vr::setVrMode can be used in any order.
+TEST_F(VrHidlTest, ReInit) {
+  EXPECT_TRUE(vr->init().isOk());
+  EXPECT_TRUE(vr->setVrMode(true).isOk());
+  EXPECT_TRUE(vr->init().isOk());
+  EXPECT_TRUE(vr->setVrMode(false).isOk());
+  EXPECT_TRUE(vr->init().isOk());
+  EXPECT_TRUE(vr->setVrMode(false).isOk());
+}
+
+int main(int argc, char **argv) {
+  ::testing::AddGlobalTestEnvironment(new VrHidlEnvironment);
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/vr/1.0/vts/functional/vts/Android.mk b/vr/1.0/vts/functional/vts/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vr/1.0/vts/functional/vts/testcases/Android.mk b/vr/1.0/vts/functional/vts/testcases/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/vr/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/__init__.py b/vr/1.0/vts/functional/vts/testcases/hal/vr/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/__init__.py
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/Android.mk
new file mode 100644
index 0000000..f9e3276
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/Android.mk
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/__init__.py b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/__init__.py
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/Android.mk
new file mode 100644
index 0000000..9388b8d
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VrHidlTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vr/hidl/host
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/AndroidTest.xml b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/AndroidTest.xml
new file mode 100644
index 0000000..1cd2a80
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS HAL VR test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+        <option name="cleanup" value="true" />
+        <option name="push" value="spec/hardware/interfaces/vr/1.0/vts/Vr.vts->/data/local/tmp/spec/Vr.vts" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VrHidlTest" />
+        <option name="test-case-path" value="vts/testcases/hal/vr/hidl/host/VrHidlTest" />
+    </test>
+</configuration>
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/VrHidlTest.py b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/VrHidlTest.py
new file mode 100644
index 0000000..d20e9ce
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/VrHidlTest.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3.4
+#
+# 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.
+#
+
+import logging
+import time
+
+from vts.runners.host import asserts
+from vts.runners.host import base_test_with_webdb
+from vts.runners.host import test_runner
+from vts.utils.python.controllers import android_device
+from vts.utils.python.profiling import profiling_utils
+
+
+class VrHidlTest(base_test_with_webdb.BaseTestWithWebDbClass):
+    """A simple testcase for the VR HIDL HAL."""
+
+    def setUpClass(self):
+        """Creates a mirror and turns on the framework-layer VR service."""
+        self.dut = self.registerController(android_device)[0]
+
+        self.dut.shell.InvokeTerminal("one")
+        self.dut.shell.one.Execute("setenforce 0")  # SELinux permissive mode
+
+        # Test using the binderized mode
+        self.dut.shell.one.Execute(
+            "setprop vts.hal.vts.hidl.get_stub true")
+
+        self.dut.hal.InitHidlHal(
+            target_type="vr",
+            target_basepaths=["/system/lib64"],
+            target_version=1.0,
+            target_package="android.hardware.vr",
+            target_component_name="IVr",
+            hw_binder_service_name=None,
+            bits=64)
+
+    def tearDownClass(self):
+        """ If profiling is enabled for the test, collect the profiling data
+            and disable profiling after the test is done.
+        """
+        if self.enable_profiling:
+            self.ProcessAndUploadTraceData()
+
+    def setUpTest(self):
+        if self.enable_profiling:
+            profiling_utils.EnableVTSProfiling(self.dut.shell.one)
+
+    def tearDownTest(self):
+        if self.enable_profiling:
+            profiling_trace_path = getattr(
+                self, self.VTS_PROFILING_TRACING_PATH, "")
+            self.ProcessTraceDataForTestCase(self.dut, profiling_trace_path)
+            profiling_utils.DisableVTSProfiling(self.dut.shell.one)
+
+    def testVrBasic(self):
+        """A simple test case which just calls each registered function."""
+        result = self.dut.hal.vr.init()
+        logging.info("init result: %s", result)
+
+        time.sleep(1)
+
+        result = self.dut.hal.vr.setVrMode(True)
+        logging.info("setVrMode(true) result: %s", result)
+
+        time.sleep(1)
+
+        result = self.dut.hal.vr.setVrMode(False)
+        logging.info("setVrMode(false) result: %s", result)
+
+
+if __name__ == "__main__":
+    test_runner.main()
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/__init__.py b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/host/__init__.py
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/Android.mk
new file mode 100644
index 0000000..691d1a4
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/Android.mk
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(call all-subdir-makefiles)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VrHidlTargetTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vr/hidl/target
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml
new file mode 100644
index 0000000..8c7a9b7
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/AndroidTest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VR HIDL HAL's target-side test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VrHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/vr_hidl_hal_test/vr_hidl_hal_test,
+            _64bit::DATA/nativetest64/vr_hidl_hal_test/vr_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="hal_hidl_gtest" />
+        <!-- Uncomment this and comment 'precondition-feature' to run this test
+             only on devices using binderized VR HALs.
+        <option name="precondition-hwbinder-service" value="android.hardware.vr" /> -->
+        <option name="precondition-feature" value="android.hardware.vr.high_performance" />
+        <option name="test-timeout" value="1m" />
+        <option name="test-config-path" value="vts/testcases/hal/vr/hidl/target/VrHidlTargetTest.config" />
+</test>
+</configuration>
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/VrHidlTargetTest.config b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/VrHidlTargetTest.config
new file mode 100644
index 0000000..ec01b5f
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target/VrHidlTargetTest.config
@@ -0,0 +1,25 @@
+{
+    "use_gae_db": true,
+    "coverage": true,
+    "modules": [{
+                    "module_name": "system/lib64/hw/vr.marlin",
+                    "git_project": {
+                        "name": "device/google/marlin",
+                        "path": "device/google/marlin"
+                    }
+                },
+                {
+                    "module_name": "system/lib64/hw/vr.sailfish",
+                    "git_project": {
+                        "name": "device/google/marlin",
+                        "path": "device/google/marlin"
+                    }
+                },
+                {
+                    "module_name": "system/lib64/hw/android.hardware.vr@1.0-impl",
+                    "git_project": {
+                        "name": "platform/hardware/interfaces",
+                        "path": "hardware/interfaces"
+                    }
+                }]
+}
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/Android.mk b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/Android.mk
new file mode 100644
index 0000000..6f60af3
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/Android.mk
@@ -0,0 +1,23 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := VrHidlTargetProfilingTest
+VTS_CONFIG_SRC_DIR := testcases/hal/vr/hidl/target_profiling
+include test/vts/tools/build/Android.host_config.mk
diff --git a/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/AndroidTest.xml b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/AndroidTest.xml
new file mode 100644
index 0000000..3bc711a
--- /dev/null
+++ b/vr/1.0/vts/functional/vts/testcases/hal/vr/hidl/target_profiling/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Config for VTS VR HIDL HAL's target-side, profiling test cases">
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.VtsFilePusher">
+        <option name="push-group" value="HidlHalTest.push" />
+    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.VtsPythonVirtualenvPreparer" />
+    <test class="com.android.tradefed.testtype.VtsMultiDeviceTest">
+        <option name="test-module-name" value="VrHidlTargetTest" />
+        <option name="binary-test-sources" value="
+            _32bit::DATA/nativetest/vr_hidl_hal_test/vr_hidl_hal_test,
+            _64bit::DATA/nativetest64/vr_hidl_hal_test/vr_hidl_hal_test,
+            "/>
+        <option name="binary-test-type" value="gtest" />
+        <option name="test-timeout" value="1m" />
+        <option name="enable-profiling" value="true" />
+    </test>
+</configuration>
+
diff --git a/vr/Android.bp b/vr/Android.bp
new file mode 100644
index 0000000..ed19a37
--- /dev/null
+++ b/vr/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "1.0/vts/functional",
+]