Merge "Revert "Add statically linked boot HAL impl in recovery""
diff --git a/audio/4.1/config/audio_policy_configuration.xsd b/audio/4.1/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..311b9c1
--- /dev/null
+++ b/audio/4.1/config/audio_policy_configuration.xsd
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the config versions supported by audio policy. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="halVersion">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Version of the interface the hal implements.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:decimal">
+            <!-- List of HAL versions supported by the framework. -->
+            <xs:enumeration value="2.0"/>
+            <xs:enumeration value="3.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="audioPolicyConfiguration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="globalConfiguration" type="globalConfiguration"/>
+                <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+                <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+                <xs:element name="surroundSound" type="surroundSound" />
+            </xs:sequence>
+            <xs:attribute name="version" type="version"/>
+        </xs:complexType>
+        <xs:key name="moduleNameKey">
+            <xs:selector xpath="modules/module"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:unique name="volumeTargetUniqueness">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@stream"/>
+            <xs:field xpath="@deviceCategory"/>
+        </xs:unique>
+        <xs:key name="volumeCurveNameKey">
+            <xs:selector xpath="volumes/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@ref"/>
+        </xs:keyref>
+    </xs:element>
+    <xs:complexType name="globalConfiguration">
+        <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="modules">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                There should be one section per audio HW module present on the platform.
+                Each <module/> contains two mandatory tags: “halVersion” and “name”.
+                The module "name" is the same as in previous .conf file.
+                Each module must contain the following sections:
+                 - <devicePorts/>: a list of device descriptors for all
+                   input and output devices accessible via this module.
+                   This contains both permanently attached devices and removable devices.
+                 - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+                 - <routes/>: list of possible connections between input
+                   and output devices or between stream and devices.
+                   A <route/> is defined by a set of 3 attributes:
+                        -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+                        -"sink": the sink involved in this route
+                        -"sources": all the sources than can be connected to the sink via this route
+                 - <attachedDevices/>: permanently attached devices.
+                   The attachedDevices section is a list of devices names.
+                   Their names correspond to device names defined in "devicePorts" section.
+                 - <defaultOutputDevice/> is the device to be used when no policy rule applies
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="module" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+                            <xs:unique name="attachedDevicesUniqueness">
+                                <xs:selector xpath="item"/>
+                                <xs:field xpath="."/>
+                            </xs:unique>
+                        </xs:element>
+                        <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+                        <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+                        <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+                        <xs:element name="routes" type="routes" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                    <xs:attribute name="halVersion" type="halVersion" use="required"/>
+                </xs:complexType>
+                <xs:unique name="mixPortNameUniqueness">
+                    <xs:selector xpath="mixPorts/mixPort"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+                <xs:key name="devicePortNameKey">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@tagName"/>
+                </xs:key>
+                <xs:unique name="devicePortUniqueness">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@type"/>
+                    <xs:field xpath="@address"/>
+                </xs:unique>
+                <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="defaultOutputDevice"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="attachedDevices/item"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <!-- The following 3 constraints try to make sure each sink port
+                     is reference in one an only one route. -->
+                <xs:key name="routeSinkKey">
+                    <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+                    <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+                    <xs:field xpath="@tagName|@name"/>
+                </xs:key>
+                <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:keyref>
+                <xs:unique name="routeUniqueness">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="attachedDevices">
+        <xs:sequence>
+            <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: separate values by space for better xsd validations. -->
+    <xs:simpleType name="audioInOutFlags">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                "|" separated list of audio_output_flags_t or audio_input_flags_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="role">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="sink"/>
+            <xs:enumeration value="source"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="mixPorts">
+        <xs:sequence>
+            <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="flags" type="audioInOutFlags"/>
+                    <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="preferredUsage" type="audioUsageList">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                When choosing the mixPort of an audio track, the audioPolicy
+                                first considers the mixPorts with a preferredUsage including
+                                the track AudioUsage preferred .
+                                If non support the track format, the other mixPorts are considered.
+                                Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+                                    the audio of all apps playing with a MEDIA usage.
+                                    It may receive audio from ALARM if there are no audio compatible
+                                    <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+                             </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="mixPortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="mixPortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- Enum values of audio_device_t in audio.h
+         TODO: generate from hidl to avoid manual sync.
+         TODO: separate source and sink in the xml for better xsd validations. -->
+    <xs:simpleType name="audioDevice">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+            <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+            <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+            <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_format_t in audio.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="audioFormat">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+            <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+            <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+            <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+            <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+            <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_XHE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_XHE"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio::common::4_0::AudioUsage
+         TODO: generate from HIDL to avoid manual sync. -->
+    <xs:simpleType name="audioUsage">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+            <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+            <xs:enumeration value="AUDIO_USAGE_ALARM" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_GAME" />
+            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioUsageList">
+        <xs:list itemType="audioUsage"/>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="samplingRates">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[0-9]+(,[0-9]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="channelMask">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma (",") separated list of channel flags
+                from audio_channel_mask_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="profile">
+        <xs:attribute name="name" type="xs:token" use="optional"/>
+        <xs:attribute name="format" type="audioFormat" use="optional"/>
+        <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+        <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
+    </xs:complexType>
+    <xs:simpleType name="gainMode">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="gains">
+        <xs:sequence>
+            <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="mode" type="gainMode" use="required"/>
+                    <xs:attribute name="channel_mask" type="channelMask" use="optional"/>
+                    <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="devicePorts">
+        <xs:sequence>
+            <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="tagName" type="xs:token" use="required"/>
+                    <xs:attribute name="type" type="audioDevice" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+                    <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+                    <xs:attribute name="default" type="xs:boolean" use="optional">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                The default device will be used if multiple have the same type
+                                and no explicit route request exists for a specific device of
+                                that type.
+                            </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="devicePortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="devicePortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="mixType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="mix"/>
+            <xs:enumeration value="mux"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="routes">
+        <xs:sequence>
+            <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation xml:lang="en">
+                        List all available sources for a given sink.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                    <xs:attribute name="type" type="mixType" use="required"/>
+                    <xs:attribute name="sink" type="xs:string" use="required"/>
+                    <xs:attribute name="sources" type="xs:string" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="volumes">
+        <xs:sequence>
+            <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: Always require a ref for better xsd validations.
+               Currently a volume could have no points nor ref
+               as it can not be forbidden by xsd 1.0.-->
+    <xs:simpleType name="volumePoint">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma separated pair of number.
+                The fist one is the framework level (between 0 and 100).
+                The second one is the volume to send to the HAL.
+                The framework will interpolate volumes not specified.
+                Their MUST be at least 2 points specified.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_stream_type_t in audio-base.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="stream">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+            <xs:enumeration value="AUDIO_STREAM_RING"/>
+            <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+            <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+            <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+            <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+            <xs:enumeration value="AUDIO_STREAM_TTS"/>
+            <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+            <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of device_category from Volume.h.
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="deviceCategory">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+            <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+            <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="volume">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Volume section defines a volume curve for a given use case and device category.
+                It contains a list of points of this curve expressing the attenuation in Millibels
+                for a given volume index from 0 to 100.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </volume>
+
+                It may also reference a reference/@name to avoid duplicating curves.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+                        ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+                <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </reference>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="stream" type="stream"/>
+        <xs:attribute name="deviceCategory" type="deviceCategory"/>
+        <xs:attribute name="ref" type="xs:token" use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="reference">
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="surroundSound">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Surround Sound section provides configuration related to handling of
+                multi-channel formats.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="formats" type="surroundFormats"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="surroundFormatsList">
+        <xs:list itemType="audioFormat" />
+    </xs:simpleType>
+    <xs:complexType name="surroundFormats">
+        <xs:sequence>
+            <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="audioFormat" use="required"/>
+                    <xs:attribute name="subformats" type="surroundFormatsList" />
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index e6ae03e..84de75e 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -57,4 +57,7 @@
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 endif
 
+# b/117506164
+LOCAL_SANITIZE := never
+
 include $(BUILD_EXECUTABLE)
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
index f27c739..f3256f1 100644
--- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
@@ -101,6 +101,7 @@
                 case -ENOENT: {
                     // No more effects available.
                     result.resize(i);
+                    break;
                 }
                 default: {
                     result.resize(0);
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 6af774e..f64028c 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -30,7 +30,6 @@
         "StatusCode",
         "SubscribeFlags",
         "SubscribeOptions",
-        "VehicleApPowerBootupReason",
         "VehicleApPowerStateConfigFlag",
         "VehicleApPowerStateReport",
         "VehicleApPowerStateReq",
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index e0b54d0..5007a6d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -36,6 +36,9 @@
 constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT;
 constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT;
 constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT;
+constexpr int WINDOW_1_LEFT = (int)VehicleAreaWindow::ROW_1_LEFT;
+constexpr int WINDOW_2_LEFT = (int)VehicleAreaWindow::ROW_2_LEFT;
+constexpr int WINDOW_2_RIGHT = (int)VehicleAreaWindow::ROW_2_RIGHT;
 constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE;
 constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
@@ -569,13 +572,20 @@
     },
 
     {.config = {.prop = toInt(VehicleProperty::DOOR_LOCK),
-                .access = VehiclePropertyAccess::READ,
+                .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
                                 VehicleAreaConfig{.areaId = DOOR_1_RIGHT}}},
      .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
                            {DOOR_1_RIGHT, {.int32Values = {1}}}}},
 
+    {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT | WINDOW_2_LEFT |
+                                                            WINDOW_2_RIGHT}}},
+     .initialAreaValues = {{WINDOW_1_LEFT | WINDOW_2_LEFT | WINDOW_2_RIGHT, {.int32Values = {0}}}}},
+
     {.config =
          {
              .prop = WHEEL_TICK,
@@ -601,12 +611,12 @@
                 .access = VehiclePropertyAccess::READ,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .configArray = {3}},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON_FULL), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
                 .access = VehiclePropertyAccess::WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
                 .access = VehiclePropertyAccess::READ_WRITE,
@@ -614,11 +624,6 @@
                 .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 100}}},
      .initialValue = {.int32Values = {100}}},
 
-    {.config = {.prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
-                .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::STATIC},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerBootupReason::USER_POWER_ON)}}},
-
     {
         .config = {.prop = OBD2_LIVE_FRAME,
                    .access = VehiclePropertyAccess::READ,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 58d8867..4f77348 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -156,13 +156,6 @@
                 // Placeholder for future implementation of VMS property in the default hal. For
                 // now, just returns OK; otherwise, hal clients crash with property not supported.
                 return StatusCode::OK;
-            case AP_POWER_STATE_REPORT:
-                // This property has different behavior between get/set.  When it is set, the value
-                //  goes to the vehicle but is NOT updated in the property store back to Android.
-                // Commented out for now, because it may mess up automated testing that use the
-                //  emulator interface.
-                // getEmulatorOrDie()->doSetValueFromClient(propValue);
-                return StatusCode::OK;
         }
     }
 
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 4d07386..4751a76 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1125,7 +1125,7 @@
     /**
      * Property to control power state of application processor
      *
-     * It is assumed that AP's power state is controller by separate power
+     * It is assumed that AP's power state is controlled by a separate power
      * controller.
      *
      * For configuration information, VehiclePropConfig.configArray can have bit flag combining
@@ -1136,7 +1136,7 @@
      *                    0 if not used.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_READ
+     * @access VehiclePropertyAccess:READ
      */
     AP_POWER_STATE_REQ = (
         0x0A00
@@ -1155,7 +1155,7 @@
 
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_WRITE
+     * @access VehiclePropertyAccess:WRITE
      */
     AP_POWER_STATE_REPORT = (
         0x0A01
@@ -2267,17 +2267,8 @@
 };
 
 enum VehicleApPowerStateReq : int32_t {
-    /** 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,
+    /** Transition Android from WAIT_FOR_VHAL to ON state */
+    ON = 0,
 
     /**
      * The power controller has requested AP to shutdown. AP can either enter
@@ -2287,8 +2278,16 @@
      * system.
      *
      * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+     *
+     * SHUTDOWN_PRPARE may be requested from either WAIT_FOR_VHAL or ON states.
      */
-    SHUTDOWN_PREPARE = 4,
+    SHUTDOWN_PREPARE = 1,
+
+    /** Cancel the shutdown and transition from SHUTDOWN_PREPARE to WAIT_FOR_VHAL state */
+    CANCEL_SHUTDOWN = 2,
+
+    /** VHAL is finished with shutdown procedures and ready for Android to suspend/shutdown */
+    FINISHED = 3,
 };
 
 /**
@@ -2314,26 +2313,30 @@
 
 enum VehicleApPowerStateReport : int32_t {
     /**
-     * AP has finished boot up, and can start shutdown if requested by power
-     * controller.
+     * Device has booted, CarService has initialized and is ready to accept commands from VHAL.
+     * Device starts in WAIT_FOR_VHAL state.  The user is not logged in, and vendor apps/services
+     * are expected to control the display and audio.
      */
-    BOOT_COMPLETE = 0x1,
+    WAIT_FOR_VHAL = 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.
+     * AP is ready to suspend and has entered WAIT_FOR_FINISHED state.
+     *
+     * 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.
      */
     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.
+     * AP is exiting from deep sleep state, and is in WAIT_FOR_VHAL state.
      */
     DEEP_SLEEP_EXIT = 0x3,
 
     /**
+     * AP remains in SHUTDOWN_PREPARE state as idle and cleanup tasks execute.
+     *
      * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
      *                 5000 ms.
      *                 If AP needs more time, it will send another POSTPONE
@@ -2342,63 +2345,31 @@
     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.
+     * AP is ready to shutdown and has entered WAIT_FOR_FINISHED state.
      *
      * 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.
+     *                 controller may not necessarily support wake-up.
      */
     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.
+     * AP has transitioned from WAIT_FOR_VHAL state to ON.
      */
-    DISPLAY_OFF = 0x6,
+    ON = 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.
+     * AP has transitions to SHUTDOWN_PREPARE state.  In this state, Garage Mode will execute idle
+     * tasks, and other services that have registered for this state transition may execute
+     * cleanup activities.
      */
-    DISPLAY_ON = 0x7,
-};
-
-/**
- * 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,
+    SHUTDOWN_PREPARE = 0x7,
 
     /**
-     * Automatic power on triggered by door unlock or any other kind of automatic
-     * user detection.
+     * AP has transitioned from SHUTDOWN_PREPARE state to WAIT_FOR_VHAL.
      */
-    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,
+    SHUTDOWN_CANCELLED = 0x8,
 };
 
 enum VehicleHwKeyInputAction : int32_t {
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index bf8b547..439c5fb 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -170,8 +170,9 @@
     acl_cb_count = 0;
     sco_cb_count = 0;
 
-    ASSERT_EQ(initialized, false);
-    bluetooth->initialize(bluetooth_cb);
+    ASSERT_FALSE(initialized);
+    // Should not be checked in production code
+    ASSERT_TRUE(bluetooth->initialize(bluetooth_cb).isOk());
 
     bluetooth_cb->SetWaitTimeout(kCallbackNameInitializationComplete,
                                  WAIT_FOR_INIT_TIMEOUT);
@@ -186,15 +187,16 @@
         bluetooth_cb->WaitForCallback(kCallbackNameInitializationComplete)
             .no_timeout);
 
-    ASSERT_EQ(initialized, true);
+    ASSERT_TRUE(initialized);
   }
 
   virtual void TearDown() override {
-    bluetooth->close();
-    handle_no_ops();
-    EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
-    EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
-    EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
+      // Should not be checked in production code
+      ASSERT_TRUE(bluetooth->close().isOk());
+      handle_no_ops();
+      EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
+      EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
+      EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
   }
 
   void setBufferSizes();
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/common/1.0/default/OWNERS
+++ b/camera/common/1.0/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/1.0/default/OWNERS
+++ b/camera/device/1.0/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.2/default/OWNERS
+++ b/camera/device/3.2/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.3/default/OWNERS b/camera/device/3.3/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.3/default/OWNERS
+++ b/camera/device/3.3/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 350f48b..7c11c61 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -1752,7 +1752,11 @@
     // TODO: see if we can save some computation by converting to YV12 here
     uint8_t* inData;
     size_t inDataSize;
-    req->frameIn->map(&inData, &inDataSize);
+    if (req->frameIn->map(&inData, &inDataSize) != 0) {
+        lk.unlock();
+        return onDeviceError("%s: V4L2 buffer map failed", __FUNCTION__);
+    }
+
     // TODO: in some special case maybe we can decode jpg directly to gralloc output?
     ATRACE_BEGIN("MJPGtoI420");
     int res = libyuv::MJPGToI420(
diff --git a/camera/device/3.4/default/OWNERS b/camera/device/3.4/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.4/default/OWNERS
+++ b/camera/device/3.4/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 5336ca9..963893a 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -48,11 +48,9 @@
 }
 
 Return<void> CameraDeviceSession::configureStreams_3_5(
-        const StreamConfiguration& /*requestedConfiguration*/,
+        const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
-    HalStreamConfiguration outStreams;
-    _hidl_cb(Status::OPERATION_NOT_SUPPORTED, outStreams);
-    return Void();
+    return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
 }
 
 Return<void> CameraDeviceSession::signalStreamFlush(
diff --git a/camera/device/3.5/default/OWNERS b/camera/device/3.5/default/OWNERS
new file mode 100644
index 0000000..369b204
--- /dev/null
+++ b/camera/device/3.5/default/OWNERS
@@ -0,0 +1,7 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+jchowdhary@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index a37e132..d21bb7c 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -100,7 +100,7 @@
 
     /** android.request.availablePhysicalCameraRequestKeys [static, int32[], hidden]
      *
-     * <p>A subset of the available request keys that can be overriden for
+     * <p>A subset of the available request keys that can be overridden for
      * physical devices backing a logical multi-camera.</p>
      */
     ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/provider/2.4/default/OWNERS
+++ b/camera/provider/2.4/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
new file mode 100644
index 0000000..49674e3
--- /dev/null
+++ b/compatibility_matrices/Android.bp
@@ -0,0 +1,77 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.legacy.xml",
+    stem: "compatibility_matrix.legacy.xml",
+    srcs: [
+        "compatibility_matrix.legacy.xml",
+    ],
+    kernel_configs: [
+        // legacy uses O kernel requirements
+        "kernel_config_o_3.18",
+        "kernel_config_o_4.4",
+        "kernel_config_o_4.9",
+    ]
+}
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.1.xml",
+    stem: "compatibility_matrix.1.xml",
+    srcs: [
+        "compatibility_matrix.1.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_o_3.18",
+        "kernel_config_o_4.4",
+        "kernel_config_o_4.9",
+    ]
+}
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.2.xml",
+    stem: "compatibility_matrix.2.xml",
+    srcs: [
+        "compatibility_matrix.2.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_o_mr1_3.18",
+        "kernel_config_o_mr1_4.4",
+        "kernel_config_o_mr1_4.9",
+    ]
+}
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.3.xml",
+    stem: "compatibility_matrix.3.xml",
+    srcs: [
+        "compatibility_matrix.3.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_p_4.4",
+        "kernel_config_p_4.9",
+        "kernel_config_p_4.14",
+    ]
+}
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.current.xml",
+    stem: "compatibility_matrix.current.xml",
+    srcs: [
+        "compatibility_matrix.current.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_current_4.4",
+        "kernel_config_current_4.9",
+        "kernel_config_current_4.14",
+    ]
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 22d0412..6be6930 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -18,72 +18,6 @@
 
 BUILD_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
 
-my_kernel_config_data := kernel/configs
-
-# Install all compatibility_matrix.*.xml to /system/etc/vintf
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.legacy.xml
-LOCAL_MODULE_STEM := compatibility_matrix.legacy.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.1.xml
-LOCAL_MODULE_STEM := compatibility_matrix.1.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.2.xml
-LOCAL_MODULE_STEM := compatibility_matrix.2.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o-mr1/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o-mr1/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o-mr1/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.3.xml
-LOCAL_MODULE_STEM := compatibility_matrix.3.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    4.4.107:$(my_kernel_config_data)/p/android-4.4 \
-    4.9.84:$(my_kernel_config_data)/p/android-4.9 \
-    4.14.42:$(my_kernel_config_data)/p/android-4.14 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.current.xml
-LOCAL_MODULE_STEM := compatibility_matrix.current.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    4.4.0:$(my_kernel_config_data)/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/android-4.9 \
-    4.14.0:$(my_kernel_config_data)/android-4.14 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-my_kernel_config_data :=
-
 # Framework Compatibility Matrix (common to all FCM versions)
 
 include $(CLEAR_VARS)
diff --git a/compatibility_matrices/build/Android.bp b/compatibility_matrices/build/Android.bp
new file mode 100644
index 0000000..42dc886
--- /dev/null
+++ b/compatibility_matrices/build/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+bootstrap_go_package {
+    name: "vintf-compatibility-matrix-soong-rules",
+    pkgPath: "android/soong/vintf-compatibility-matrix",
+    deps: [
+        "blueprint",
+        "blueprint-proptools",
+        "kernel-config-soong-rules",
+        "soong",
+        "soong-android",
+    ],
+    srcs: [
+        "vintf_compatibility_matrix.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/compatibility_matrices/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
new file mode 100644
index 0000000..e48f993
--- /dev/null
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -0,0 +1,132 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package vintf
+
+import (
+	"fmt"
+	"io"
+	"strings"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/kernel/configs"
+)
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+var (
+	pctx = android.NewPackageContext("android/vintf")
+
+	assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
+		Command:     `${assembleVintfCmd} -i ${inputs} -o ${out}`,
+		CommandDeps: []string{"${assembleVintfCmd}"},
+		Description: "assemble_vintf -i ${inputs}",
+	}, "inputs")
+
+	kernelConfigTag = dependencyTag{name: "kernel-config"}
+)
+
+const (
+	relpath = "vintf"
+)
+
+type vintfCompatibilityMatrixProperties struct {
+	// set the name of the output
+	Stem *string
+
+	// list of source compatibility matrix XML files
+	Srcs []string
+
+	// list of kernel_config modules to be combined to final output
+	Kernel_configs []string
+}
+
+type vintfCompatibilityMatrixRule struct {
+	android.ModuleBase
+	properties vintfCompatibilityMatrixProperties
+
+	genFile android.WritablePath
+}
+
+func init() {
+	pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
+	android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
+}
+
+func vintfCompatibilityMatrixFactory() android.Module {
+	g := &vintfCompatibilityMatrixRule{}
+	g.AddProperties(&g.properties)
+	android.InitAndroidArchModule(g, android.DeviceSupported, android.MultilibCommon)
+	return g
+}
+
+var _ android.AndroidMkDataProvider = (*vintfCompatibilityMatrixRule)(nil)
+
+func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	android.ExtractSourcesDeps(ctx, g.properties.Srcs)
+	ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
+}
+
+func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+	outputFilename := proptools.String(g.properties.Stem)
+	if outputFilename == "" {
+		outputFilename = g.Name()
+	}
+
+	inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
+	ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
+		if k, ok := m.(*configs.KernelConfigRule); ok {
+			inputPaths = append(inputPaths, k.OutputPath())
+		} else {
+			ctx.PropertyErrorf("kernel_config",
+				"module %q is not a kernel_config", ctx.OtherModuleName(m))
+		}
+	})
+
+	g.genFile = android.PathForModuleGen(ctx, outputFilename)
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        assembleVintfRule,
+		Description: "Framework Compatibility Matrix",
+		Implicits:   inputPaths,
+		Output:      g.genFile,
+		Args: map[string]string{
+			"inputs": strings.Join(inputPaths.Strings(), ":"),
+		},
+	})
+
+	ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
+}
+
+func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(g.genFile),
+		Extra: []android.AndroidMkExtraFunc{
+			func(w io.Writer, outputFile android.Path) {
+				fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", relpath)
+				if proptools.String(g.properties.Stem) != "" {
+					fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
+				}
+			},
+		},
+	}
+}
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index fc7bad6..e13d293 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -445,7 +445,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1.0-1</version>
+        <version>1.0</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index ff5b3e8..b64ff86 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -317,6 +317,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
         <version>1.0-2</version>
         <interface>
@@ -461,7 +469,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
diff --git a/confirmationui/support/src/cbor.cpp b/confirmationui/support/src/cbor.cpp
index e7ea164..3685521 100644
--- a/confirmationui/support/src/cbor.cpp
+++ b/confirmationui/support/src/cbor.cpp
@@ -36,11 +36,14 @@
             *pos++ = getByte(value, 6);
             *pos++ = getByte(value, 5);
             *pos++ = getByte(value, 4);
+            [[fallthrough]];
         case 4:
             *pos++ = getByte(value, 3);
             *pos++ = getByte(value, 2);
+            [[fallthrough]];
         case 2:
             *pos++ = getByte(value, 1);
+            [[fallthrough]];
         case 1:
             *pos++ = value;
             break;
diff --git a/current.txt b/current.txt
index 4709ab3..a7989d4 100644
--- a/current.txt
+++ b/current.txt
@@ -388,8 +388,9 @@
 2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
 f61b616732d8f374e030f90575d7eba3ecc99d209a05b945949ba892bcb81e1d android.hardware.camera.device@3.2::ICameraDeviceSession
 684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
-a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types
+dd2436f251a90f3e5e7ed773b1aeae21e381b00ae26b10ebe3a1001c894e5980 android.hardware.camera.metadata@3.3::types
 da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+78886339f2c848cf13c1edd3ebba63f89796b2620d3bf3b5c21d038a53519ba0 android.hardware.gnss@1.0::IGnssMeasurementCallback
 b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
 1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
index 3267499..467fc6d 100644
--- a/fastboot/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -14,9 +14,10 @@
         "android.hidl.base@1.0",
     ],
     types: [
-        "Status",
+        "FileSystemType",
         "Result",
+        "Status",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal
index b27c2e0..d3489e6 100644
--- a/gnss/1.0/IGnssMeasurementCallback.hal
+++ b/gnss/1.0/IGnssMeasurementCallback.hal
@@ -124,6 +124,12 @@
         /**
          * A set of flags indicating the validity of the fields in this data
          * structure.
+         *
+         * Fields for which there is no corresponding flag must be filled in
+         * with a valid value.  For convenience, these are marked as mandatory.
+         *
+         * Others fields may have invalid information in them, if not marked as
+         * valid by the corresponding bit in gnssClockFlags.
          */
         bitfield<GnssClockFlags> gnssClockFlags;
 
@@ -155,7 +161,7 @@
          * Sub-nanosecond accuracy can be provided by means of the 'biasNs' field.
          * The value contains the timeUncertaintyNs in it.
          *
-         * This field is mandatory.
+         * This value is mandatory.
          */
         int64_t timeNs;
 
@@ -172,29 +178,31 @@
 
         /**
          * The difference between hardware clock ('time' field) inside GNSS receiver
-         * and the true GNSS time since 0000Z, January 6, 1980, in nanoseconds.
+         * and the true GPS 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)
+         *      local estimate of GPS 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.
+         * If receiver has computed time for a non-GPS constellation, the time offset of
+         * that constellation versus GPS time must be applied to fill this value.
+         *
+         * The error estimate for the sum of this and the biasNs is the biasUncertaintyNs.
+         *
+         * If the data is available gnssClockFlags must contain HAS_FULL_BIAS.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         int64_t fullBiasNs;
 
         /**
-         * Sub-nanosecond bias.
+         * Sub-nanosecond bias - used with fullBiasNS, see fullBiasNs for details.
+         *
          * 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.
+         * If the data is available gnssClockFlags must contain HAS_BIAS.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double biasNs;
 
@@ -203,9 +211,12 @@
          * 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.
+         * The caller is responsible for using this uncertainty (it can be very
+         * large before the GPS time has been fully resolved.)
+         *
+         * If the data is available gnssClockFlags must contain HAS_BIAS_UNCERTAINTY.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double biasUncertaintyNs;
 
@@ -216,10 +227,9 @@
          * 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.
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double driftNsps;
 
@@ -228,15 +238,15 @@
          * 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.
+         * If the data is available gnssClockFlags must contain HAS_DRIFT_UNCERTAINTY.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double driftUncertaintyNsps;
 
         /**
-         * When there are any discontinuities in the HW clock, this field is
-         * mandatory.
+         * This field must be incremented, when there are discontinuities in the
+         * hardware clock.
          *
          * 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)
@@ -262,6 +272,8 @@
          * 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.
+         *
+         * This value is mandatory.
          */
         uint32_t hwClockDiscontinuityCount;
 
@@ -280,17 +292,26 @@
         /**
          * A set of flags indicating the validity of the fields in this data
          * structure.
+         *
+         * Fields for which there is no corresponding flag must be filled in
+         * with a valid value.  For convenience, these are marked as mandatory.
+         *
+         * Others fields may have invalid information in them, if not marked as
+         * valid by the corresponding bit in flags.
          */
         bitfield<GnssMeasurementFlags> flags;
 
         /**
          * Satellite vehicle ID number, as defined in GnssSvInfo::svid
-         * This is a mandatory value.
+         *
+         * This value is mandatory.
          */
         int16_t svid;
 
         /**
          * Defines the constellation of the given SV.
+         *
+         * This value is mandatory.
          */
         GnssConstellationType constellation;
 
@@ -302,8 +323,10 @@
          *      measurement time = GnssClock::timeNs + timeOffsetNs
          *
          * It provides an individual time-stamp for the measurement, and allows
-         * sub-nanosecond accuracy.
-         * This is a mandatory value.
+         * sub-nanosecond accuracy. It may be zero if all measurements are
+         * aligned to a common time.
+         *
+         * This value is mandatory.
          */
         double timeOffsetNs;
 
@@ -313,7 +336,7 @@
          * Based on the sync state, the 'received GNSS tow' field must be interpreted
          * accordingly.
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         bitfield<GnssMeasurementState> state;
 
@@ -413,7 +436,7 @@
          * 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.
+         * This value is mandatory.
          */
         double cN0DbHz;
 
@@ -449,7 +472,7 @@
          * 1-Sigma uncertainty of the pseudorangeRateMps.
          * The uncertainty is represented as an absolute (single sided) value.
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         double pseudorangeRateUncertaintyMps;
 
@@ -457,7 +480,7 @@
          * 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.
+         * This value is mandatory.
          */
         bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState;
 
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 405990e..1f8bbdb 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -11,12 +11,14 @@
         "IAccessor.hal",
         "IClientManager.hal",
         "IConnection.hal",
+        "IObserver.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
         "Buffer",
+        "BufferInvalidationMessage",
         "BufferStatus",
         "BufferStatusMessage",
         "ResultStatus",
diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal
index ab7c02d..66707fe 100644
--- a/media/bufferpool/2.0/IAccessor.hal
+++ b/media/bufferpool/2.0/IAccessor.hal
@@ -17,6 +17,7 @@
 package android.hardware.media.bufferpool@2.0;
 
 import IConnection;
+import IObserver;
 /**
  * IAccessor creates IConnection which is used from IClientManager in order to
  * use functionality of the specified buffer pool.
@@ -49,6 +50,13 @@
      * made and kept private. Also part of transaction ID is a sender ID in
      * order to prevent fake transactions from other clients. This must be
      * verified with an FMQ message from a buffer pool.
+
+     * @param observer The buffer pool event observer from the client.
+     *     Observer is provided to ensure FMQ messages are processed even when
+     *     client processes are idle. Buffer invalidation caused by
+     *     reconfiguration does not call observer. Buffer invalidation caused
+     *     by termination of pipeline call observer in order to ensure
+     *     invalidation is done after pipeline completion.
      *
      * @return status The status of the call.
      *     OK               - A connection is made successfully.
@@ -64,7 +72,7 @@
      * @return fromFmqDesc FMQ descriptor. The descriptor is used to
      *     receive buffer invalidation messages from the buffer pool.
      */
-    connect()
+    connect(IObserver observer)
         generates (ResultStatus status, IConnection connection,
                    int64_t connectionId,
                    fmq_sync<BufferStatusMessage> toFmqDesc,
diff --git a/media/bufferpool/2.0/IObserver.hal b/media/bufferpool/2.0/IObserver.hal
new file mode 100644
index 0000000..a998836
--- /dev/null
+++ b/media/bufferpool/2.0/IObserver.hal
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.bufferpool@2.0;
+
+/**
+ * IObserver listens on notifications from the buffer pool. On receiving
+ * notifications, FMQ messages from the specific buffer pool which are already
+ * in the FMQ are processed.
+ */
+interface IObserver {
+
+    /**
+     * The specific buffer pool sent a message to the client. Calling this
+     * method from the buffer pool enforces a buffer pool client process the
+     * message.
+     *
+     * @param connectionId the connection Id of the specific buffer pool client
+     */
+    oneway onMessage(int64_t connectionId);
+};
diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal
index 456e4aa..597e7b3 100644
--- a/media/bufferpool/2.0/types.hal
+++ b/media/bufferpool/2.0/types.hal
@@ -65,6 +65,8 @@
     TRANSFER_OK         = 7,
     /** Buffer transaction failure. */
     TRANSFER_ERROR      = 8,
+    /** Buffer invalidation ack. */
+    INVALIDATION_ACK    = 9,
 };
 
 /**
@@ -98,6 +100,7 @@
  * buffers as soon as possible upon receiving the message.
  */
 struct BufferInvalidationMessage {
+    uint32_t messageId;
     /**
      * Buffers from fromBufferId to toBufferId must be invalidated.
      * fromBufferId is inclusive, but toBufferId is not inclusive.
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
new file mode 100644
index 0000000..c37c22b
--- /dev/null
+++ b/media/c2/1.0/Android.bp
@@ -0,0 +1,51 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.media.c2@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IComponent.hal",
+        "IComponentInterface.hal",
+        "IComponentListener.hal",
+        "IComponentStore.hal",
+        "IConfigurable.hal",
+        "IInputSurface.hal",
+        "IInputSurfaceConnection.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "BaseBlock",
+        "Block",
+        "Buffer",
+        "FieldDescriptor",
+        "FieldId",
+        "FieldSupportedValues",
+        "FieldSupportedValuesQuery",
+        "FieldSupportedValuesQueryResult",
+        "FrameData",
+        "InfoBuffer",
+        "ParamDescriptor",
+        "ParamField",
+        "ParamFieldValues",
+        "SettingResult",
+        "Status",
+        "StructDescriptor",
+        "Work",
+        "WorkBundle",
+        "WorkOrdinal",
+        "Worklet",
+    ],
+    gen_java: false,
+}
+
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
new file mode 100644
index 0000000..7fd551f
--- /dev/null
+++ b/media/c2/1.0/IComponent.hal
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+import android.hardware.media.omx@1.0::IGraphicBufferSource;
+
+import IConfigurable;
+import IComponentInterface;
+import IComponentListener;
+import IInputSurface;
+import IInputSurfaceConnection;
+
+/**
+ * Interface for a Codec2 component corresponding to API level 1.0 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
+ */
+interface IComponent {
+
+    // METHODS AVAILABLE WHEN RUNNING
+    // =========================================================================
+
+    /**
+     * Queues up work for the component.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * It is acceptable for this method to return `OK` and return an error value
+     * using the IComponentListener::onWorkDone() callback.
+     *
+     * @param workBundle `WorkBundle` object containing a list of `Work` objects
+     *     to queue to the component.
+     * @return status Status of the call, which may be
+     *   - `OK`        - Works in @p workBundle were successfully queued.
+     *   - `BAD_INDEX` - Some component id in some `Worklet` is not valid.
+     *   - `CANNOT_DO` - The components are not tunneled but some `Work` object
+     *                   contains tunneling information.
+     *   - `NO_MEMORY` - Not enough memory to queue @p workBundle.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    queue(WorkBundle workBundle) generates (Status status);
+
+    /**
+     * Discards and abandons any pending `Work` items for the component.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * `Work` that could be immediately abandoned/discarded must be returned in
+     * @p flushedWorkBundle. The order in which queued `Work` items are
+     * discarded can be arbitrary.
+     *
+     * `Work` that could not be abandoned or discarded immediately must be
+     * marked to be discarded at the earliest opportunity, and must be returned
+     * via IComponentListener::onWorkDone(). This must be completed within
+     * 500ms.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been successfully flushed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return flushedWorkBundle `WorkBundle` object containing flushed `Work`
+     *     items.
+     */
+    flush(
+        ) generates (
+            Status status,
+            WorkBundle flushedWorkBundle
+        );
+
+    /**
+     * Drains the component, and optionally downstream components. This is a
+     * signalling method; as such it does not wait for any work completion.
+     *
+     * The last `Work` item is marked as "drain-till-here", so the component is
+     * notified not to wait for further `Work` before it processes what is
+     * already queued. This method can also be used to set the end-of-stream
+     * flag after `Work` has been queued. Client can continue to queue further
+     * `Work` immediately after this method returns.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * `Work` that is completed must be returned via
+     * IComponentListener::onWorkDone().
+     *
+     * @param withEos Whether to drain the component with marking end-of-stream.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The drain request has been successfully recorded.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    drain(bool withEos) generates (Status status);
+
+    /**
+     * Starts using a surface for output.
+     *
+     * This method must not block.
+     *
+     * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+     *     output surface.
+     * @param surface Output surface.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an output surface.
+     *   - `REFUSED`   - The output surface cannot be accessed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    setOutputSurface(
+            uint64_t blockPoolId,
+            IGraphicBufferProducer surface
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Starts using an input surface.
+     *
+     * The component must be in running state.
+     *
+     * @param inputSurface Input surface to connect to.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
+     */
+    connectToInputSurface(
+            IInputSurface inputSurface
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
+
+    /**
+     * Starts using an OMX input surface.
+     *
+     * The component must be in running state.
+     *
+     * This method is similar to connectToInputSurface(), but it takes an OMX
+     * input surface (as a pair of `IGraphicBufferProducer` and
+     * `IGraphicBufferSource`) instead of Codec2's own `IInputSurface`.
+     *
+     * @param producer Producer component of an OMX input surface.
+     * @param source Source component of an OMX input surface.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an OMX input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
+     */
+    connectToOmxInputSurface(
+            IGraphicBufferProducer producer,
+            IGraphicBufferSource source
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
+
+    /**
+     * Stops using an input surface.
+     *
+     * The component must be in running state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `NOT_FOUND` - The component is not connected to an input surface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    disconnectFromInputSurface() generates (Status Status);
+
+    /**
+     * Creates a local `C2BlockPool` backed by the given allocator and returns
+     * its id.
+     *
+     * The returned @p blockPoolId is the only way the client can refer to a
+     * `C2BlockPool` object in the component. The id can be passed to
+     * setOutputSurface() or used in some C2Param objects later.
+     *
+     * The created `C2BlockPool` object can be destroyed by calling
+     * destroyBlockPool(), reset() or release(). reset() and release() must
+     * destroy all `C2BlockPool` objects that have been created.
+     *
+     * @param allocatorId Id of a `C2Allocator`.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to create the pool.
+     *   - `BAD_VALUE` - @p allocatorId is not recognized.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return blockPoolId Id of the created C2BlockPool object. This may be
+     *     used in setOutputSurface() if the allocator
+     * @return configurable Configuration interface for the created pool. This
+     *     must not be null.
+     */
+    createBlockPool(uint32_t allocatorId) generates (
+        Status status,
+        uint64_t blockPoolId,
+        IConfigurable configurable
+    );
+
+    /**
+     * Destroys a local block pool previously created by createBlockPool().
+     *
+     * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
+     *      createBlockPool().
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - The supplied blockPoolId is not valid.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    destroyBlockPool(uint64_t blockPoolId) generates (Status status);
+
+    // STATE CHANGE METHODS
+    // =========================================================================
+
+    /**
+     * Starts the component.
+     *
+     * This method must be supported in stopped state as well as tripped state.
+     *
+     * If the return value is `OK`, the component must be in the running state.
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. Otherwise, the component must be in
+     * the stopped state.
+     *
+     * If a component is in the tripped state and start() is called while the
+     * component configuration still results in a trip, start() must succeed and
+     * a new onTripped() callback must be used to communicate the configuration
+     * conflict that results in the new trip.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has started successfully.
+     *   - `BAD_STATE` - Component is not in stopped or tripped state.
+     *   - `DUPLICATE` - When called during another start call from another
+     *                   thread.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    start() generates (Status status);
+
+    /**
+     * Stops the component.
+     *
+     * This method must be supported in running (including tripped) state.
+     *
+     * This method must return withing 500ms.
+     *
+     * Upon this call, all pending `Work` must be abandoned.
+     *
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
+     *
+     * This does not alter any settings and tunings that may have resulted in a
+     * tripped state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has stopped successfully.
+     *   - `BAD_STATE` - Component is not in running state.
+     *   - `DUPLICATE` - When called during another stop call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    stop() generates (Status status);
+
+    /**
+     * Resets the component.
+     *
+     * This method must be supported in all (including tripped) states other
+     * than released.
+     *
+     * This method must be supported during any other blocking call.
+     *
+     * This method must return withing 500ms.
+     *
+     * When this call returns, if @p status is `OK`, all `Work` items must
+     * have been abandoned, and all resources (including `C2BlockPool` objects
+     * previously created by createBlockPool()) must have been released.
+     *
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
+     *
+     * This brings settings back to their default, "guaranteeing" no tripped
+     * state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been reset.
+     *   - `BAD_STATE` - Component is in released state.
+     *   - `DUPLICATE` - When called during another reset call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    reset() generates (Status status);
+
+    /**
+     * Releases the component.
+     *
+     * This method must be supported in stopped state.
+     *
+     * This method destroys the component. Upon return, if @p status is `OK` or
+     * `DUPLICATE`, all resources must have been released.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been released.
+     *   - `BAD_STATE` - The component is running.
+     *   - `DUPLICATE` - The component is already released.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    release() generates (Status status);
+
+    /**
+     * Returns the @ref IComponentInterface instance associated to this
+     * component.
+     *
+     * An @p IConfigurable instance for the component can be obtained by calling
+     * IComponentInterface::getConfigurable() on the returned @p intf.
+     *
+     * @return intf `IComponentInterface` instance. This must not be null.
+     */
+    getInterface() generates (IComponentInterface intf);
+};
+
diff --git a/media/c2/1.0/IComponentInterface.hal b/media/c2/1.0/IComponentInterface.hal
new file mode 100644
index 0000000..a007d02
--- /dev/null
+++ b/media/c2/1.0/IComponentInterface.hal
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import IConfigurable;
+
+/**
+ * Component interface object. This object contains all of the configurations of
+ * a potential or actual component. It can be created and used independently of
+ * an actual Codec2 component to query supported parameters for various
+ * component settings, and configurations for a potential component.
+ *
+ * An actual component exposes this interface via IComponent::getInterface().
+ */
+interface IComponentInterface {
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * interface.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal
new file mode 100644
index 0000000..70d5fb2
--- /dev/null
+++ b/media/c2/1.0/IComponentListener.hal
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+/**
+ * Callback interface for handling notifications from @ref IComponent.
+ */
+interface IComponentListener {
+
+    /**
+     * Notify the listener that some `Work` items have been completed.
+     *
+     * All the input buffers in the returned `Work` objects must not be used by
+     * the component after onWorkDone() is called.
+     *
+     * @param workBundle List of completed `Work` objects.
+     */
+    oneway onWorkDone(WorkBundle workBundle);
+
+    /**
+     * Notify the listener that the component is tripped.
+     *
+     * @param settingResults List of failures.
+     */
+    oneway onTripped(vec<SettingResult> settingResults);
+
+    /**
+     * Notify the listener of an error.
+     *
+     * @param status Error type. @p status may be `OK`, which means that an
+     *     error has occurred, but the error type does not fit into the type
+     *     `Status`. In this case, additional information is provided by
+     *     @p errorCode.
+     * @param errorCode Additional error information. The framework may not
+     *     recognize the meaning of this value.
+     */
+    oneway onError(Status status, uint32_t errorCode);
+
+    /**
+     * Information about rendering of a frame to a `Surface`.
+     */
+    struct RenderedFrame {
+        /**
+         * Id of the `BufferQueue` containing the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::getUniqueId().
+         */
+        uint64_t bufferQueueId;
+        /**
+         * Id of the slot of the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::dequeueBuffer() or
+         * IGraphicBufferProducer::attachBuffer().
+         */
+        int32_t slotId;
+        /**
+         * Timestamp the rendering happened.
+         *
+         * The reference point for the timestamp is determined by the
+         * `BufferQueue` that performed the rendering.
+         */
+        int64_t timestampNs;
+    };
+
+    /**
+     * Notify the listener that frames have been rendered.
+     *
+     * @param renderedFrames List of @ref RenderedFrame objects.
+     */
+    oneway onFramesRendered(vec<RenderedFrame> renderedFrames);
+
+    /**
+     * Identifying information for an input buffer previously queued to the
+     * component via IComponent::queue().
+     */
+    struct InputBuffer {
+        /**
+         * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
+         * object that was previously queued.
+         */
+        uint64_t frameIndex;
+        /**
+         * This value is an index into `Work::input.buffers` (which is an array)
+         * in a `Work` object that was previously queued.
+         */
+        uint32_t arrayIndex;
+    };
+
+    /**
+     * Notify the listener that some input buffers are no longer needed by the
+     * component, and hence can be released or reused by the client.
+     *
+     * Input buffers that are contained in a `Work` object returned by an
+     * earlier onWorkDone() call are assumed released, so they must not appear
+     * in any onInputBuffersReleased() calls. That means
+     * onInputBuffersReleased() must only report input buffers that are released
+     * before the output in the same `Work` item is produced. However, it is
+     * possible for an input buffer to be returned by onWorkDone() after it has
+     * been reported by onInputBuffersReleased().
+     *
+     * @note onWorkDone() and onInputBuffersReleased() both notify the client
+     * that input buffers are no longer needed. However, in order to minimize
+     * IPC calls, onInputBuffersReleased() should be called only when
+     * onWorkDone() cannot be called, e.g., the component needs more input
+     * before an output can be produced.
+     *
+     * @param inputBuffers List of `InputBuffer` objects, identifying input
+     * buffers that are no longer needed by the component.
+     */
+    oneway onInputBuffersReleased(vec<InputBuffer> inputBuffers);
+};
+
diff --git a/media/c2/1.0/IComponentStore.hal b/media/c2/1.0/IComponentStore.hal
new file mode 100644
index 0000000..6a57c38
--- /dev/null
+++ b/media/c2/1.0/IComponentStore.hal
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import android.hardware.media.bufferpool@2.0::IClientManager;
+import IComponentInterface;
+import IComponentListener;
+import IComponent;
+import IConfigurable;
+import IInputSurface;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ */
+interface IComponentStore {
+
+    /**
+     * Creates a component by name.
+     *
+     * @param name Name of the component to create. This must match one of the
+     *     names returned by listComponents().
+     * @param listener Callback receiver.
+     * @param pool `IClientManager` object of the BufferPool in the client
+     *     process. This may be null if the client does not own a BufferPool.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component was created successfully.
+     *   - `NOT_FOUND` - There is no component with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return comp The created component if @p status is `OK`.
+     *
+     * @sa IComponentListener.
+     */
+    createComponent(
+            string name,
+            IComponentListener listener,
+            IClientManager pool
+        ) generates (
+            Status status,
+            IComponent comp
+        );
+
+    /**
+     * Creates a component interface by name.
+     *
+     * @param name Name of the component interface to create. This should match
+     *     one of the names returned by listComponents().
+     * @return status Status of the call, which may be
+     *   - `OK         - The component interface was created successfully.
+     *   - `NOT_FOUND` - There is no component interface with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component interface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return compIntf The created component interface if @p status is `OK`.
+     */
+    createInterface(
+            string name
+        ) generates (
+            Status status,
+            IComponentInterface compIntf
+        );
+
+    /**
+     * Component traits.
+     */
+    struct ComponentTraits {
+        /**
+         * Name of the component. This must be unique for each component.
+         *
+         * This name is use to identify the component to create in
+         * createComponent() and createComponentInterface().
+         */
+        string name;
+
+        enum Domain : uint32_t {
+            OTHER = 0,
+            VIDEO,
+            AUDIO,
+            IMAGE,
+        };
+        /**
+         * Component domain.
+         */
+        Domain domain;
+
+        enum Kind : uint32_t {
+            OTHER = 0,
+            DECODER,
+            ENCODER,
+        };
+        /**
+         * Component kind.
+         */
+        Kind kind;
+
+        /**
+         * Rank used by `MediaCodecList` to determine component ordering. Lower
+         * value means higher priority.
+         */
+        uint32_t rank;
+
+        /**
+         * MIME type.
+         */
+        string mediaType;
+
+        /**
+         * Aliases for component name for backward compatibility.
+         *
+         * Multiple components can have the same alias (but not the same
+         * component name) as long as their media types differ.
+         */
+        vec<string> aliases;
+    };
+
+    /**
+     * Returns the list of components supported by this component store.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK         - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return traits List of component traits for all components supported by
+     *     this store (in no particular order).
+     */
+    listComponents() generates (
+            Status status,
+            vec<ComponentTraits> traits
+        );
+
+    /**
+     * Creates a persistent input surface that can be used as an input surface
+     * for any IComponent instance
+     *
+     * @return status Status of the call, which may be
+     *   - `OK         - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return surface A persistent input surface. This may be null to indicate
+     *     an error.
+     */
+    createInputSurface() generates (
+            Status status,
+            IInputSurface surface
+        );
+
+    /**
+     * Returns a list of `StructDescriptor` objects for a set of requested
+     * C2Param structure indices that this store is aware of.
+     *
+     * This operation must be performed at best effort, e.g. the component
+     * store must simply ignore all struct indices that it is not aware of.
+     *
+     * @param indices Indices of C2Param structures to describe.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - Some indices were not known.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return structs List of `StructDescriptor` objects.
+     */
+    getStructDescriptors(
+            vec<ParamIndex> indices
+        ) generates (
+            Status status,
+            vec<StructDescriptor> structs
+        );
+
+    /**
+     * Copies the contents of @p src into @p dst without changing the format of
+     * @p dst.
+     *
+     * @param src Source buffer.
+     * @param dst Destination buffer.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The copy is successful.
+     *   - `CANNOT_DO` - @p src and @p dst are not compatible.
+     *   - `REFUSED`   - No permission to copy.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    copyBuffer(Buffer src, Buffer dst) generates (Status status);
+
+    /**
+     * Returns the `IClientManager` object for the component's BufferPool.
+     *
+     * @return pool If the component store supports receiving buffers via
+     *     BufferPool API, @p pool must be a valid `IClientManager` instance.
+     *     Otherwise, @p pool must be null.
+     */
+    getPoolClientManager() generates (IClientManager pool);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * store.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IConfigurable.hal b/media/c2/1.0/IConfigurable.hal
new file mode 100644
index 0000000..31dc4d3
--- /dev/null
+++ b/media/c2/1.0/IConfigurable.hal
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+/**
+ * Generic configuration interface presented by all configurable Codec2 objects.
+ *
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
+ */
+interface IConfigurable {
+    /**
+     * Returns the id of the object. This must be unique among all objects of
+     * the same type hosted by the same store.
+     *
+     * @return id Id of the object.
+     */
+    getId() generates (uint32_t id);
+
+    /**
+     * Returns the name of the object.
+     *
+     * This must match the name that was supplied during the creation of the
+     * object.
+     *
+     * @return name Name of the object.
+     */
+    getName() generates (string name);
+
+    /**
+     * Queries a set of parameters from the object.
+     *
+     * Querying is performed at best effort: the object must query all supported
+     * parameters and skip unsupported ones (which may include parameters that
+     * could not be allocated). Any errors are communicated in the return value.
+     *
+     * If @p mayBlock is false, this method must not block. All parameter
+     * queries that require blocking must be skipped.
+     *
+     * If @p mayBlock is true, a query may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation is not completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
+     *
+     * @note The order of C2Param objects in @p param does not depend on the
+     *     order of C2Param structure indices in @p indices.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released. This call must not change the state nor the
+     * internal configuration of the component.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param indices List of C2Param structure indices to query.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - All parameters could be queried.
+     *   - `BAD_INDEX` - All supported parameters could be queried, but some
+     *                   parameters were not supported.
+     *   - `NO_MEMORY` - Could not allocate memory for a supported parameter.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return params Flattened representation of C2Param objects.
+     *
+     * @sa Params.
+     */
+    query(
+            vec<ParamIndex> indices,
+            bool mayBlock
+        ) generates (
+            Status status,
+            Params params
+        );
+
+    /**
+     * Sets a set of parameters for the object.
+     *
+     * Tuning is performed at best effort: the object must update all supported
+     * configurations at best effort and skip unsupported parameters. Any errors
+     * are communicated in the return value and in @p failures.
+     *
+     * A non-strict parameter update with an unsupported value shall cause an
+     * update to the closest supported value. A strict parameter update with an
+     * unsupported value shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is false, this method must not block. An update that
+     * requires blocking shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is true, an update may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * The final values for all parameters set are propagated back to the caller
+     * in @p params.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @note Parameter tuning @e does depend on the order of the tuning
+     * parameters, e.g., some parameter update may enable some subsequent
+     * parameter update.
+     *
+     * @param inParams Requested parameter updates.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - All parameters could be updated successfully.
+     *   - `BAD_INDEX` - All supported parameters could be updated successfully,
+     *                   but some parameters were not supported.
+     *   - `NO_MEMORY` - Some supported parameters could not be updated
+     *                   successfully because they contained unsupported values.
+     *                   These are returned in @p failures.
+     *   - `BLOCKING`  - Setting some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return failures List of update failures.
+     * @return outParams Flattened representation of configured parameters. The
+     *     order of parameters in @p outParams is based on the order of
+     *     requested updates in @p inParams.
+     *
+     * @sa SettingResult.
+     */
+    config(
+            Params inParams,
+            bool mayBlock
+        ) generates (
+            Status status,
+            vec<SettingResult> failures,
+            Params outParams
+        );
+
+    // REFLECTION MECHANISM
+    // =========================================================================
+
+    /**
+     * Returns a list of supported parameters within a selected range of C2Param
+     * structure indices.
+     *
+     * @param start The first index of the selected range.
+     * @param count The length of the selected range.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     * @return params List of supported parameters in the selected range. This
+     *     list may have fewer than @p count elements if some indices in the
+     *     range are not supported.
+     *
+     * @sa ParamDescriptor.
+     */
+    querySupportedParams(
+            uint32_t start,
+            uint32_t count
+        ) generates (
+            Status status,
+            vec<ParamDescriptor> params
+        );
+
+    /**
+     * Retrieves the supported values for the queried fields.
+     *
+     * The object must process all fields queried even if some queries fail.
+     *
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation cannot be completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param inFields List of field queries.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `BAD_INDEX` - At least one field was not recognized as a component
+     *                   field.
+     *   - `BLOCKING`  - Querying some fields requires blocking, but @p mayblock
+     *                   is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return outFields List of supported values and results for the
+     *     supplied queries.
+     *
+     * @sa FieldSupportedValuesQuery, FieldSupportedValuesQueryResult.
+     */
+    querySupportedValues(
+            vec<FieldSupportedValuesQuery> inFields,
+            bool mayBlock
+        ) generates (
+            Status status,
+            vec<FieldSupportedValuesQueryResult> outFields
+        );
+
+};
+
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
new file mode 100644
index 0000000..25c6c8e
--- /dev/null
+++ b/media/c2/1.0/IInputSurface.hal
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+
+import IConfigurable;
+
+/**
+ * Input surface for a Codec2 component.
+ *
+ * An <em>input surface</em> is an instance of `IInputSurface`, which may be
+ * created by calling IComponentStore::createInputSurface(). Once created, the
+ * client may
+ *   1. write data to it via the `IGraphicBufferProducer` interface; and
+ *   2. use it as input to a Codec2 encoder.
+ *
+ * @sa IInputSurfaceConnection, IComponentStore::createInputSurface(),
+ *     IComponent::connectToInputSurface().
+ */
+interface IInputSurface {
+    /**
+     * Returns the producer interface into the internal buffer queue.
+     *
+     * @return producer `IGraphicBufferProducer` instance. This must not be
+     * null.
+     */
+    getGraphicBufferProducer() generates (IGraphicBufferProducer producer);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this input surface.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IInputSurfaceConnection.hal b/media/c2/1.0/IInputSurfaceConnection.hal
new file mode 100644
index 0000000..efd9c6e
--- /dev/null
+++ b/media/c2/1.0/IInputSurfaceConnection.hal
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import IConfigurable;
+
+/**
+ * Connection between a component and an input surface.
+ *
+ * An instance of `IInputSurfaceConnection` contains an `IConfigurable`
+ * interface for querying and configuring properties of the connection.
+ */
+interface IInputSurfaceConnection {
+    /**
+     * Returns the @ref IConfigurable instance associated to this connection.
+     *
+     * This can be used to customize the connection.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal
new file mode 100644
index 0000000..7b75041
--- /dev/null
+++ b/media/c2/1.0/types.hal
@@ -0,0 +1,832 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import android.hardware.media.bufferpool@2.0::BufferStatusMessage;
+
+/**
+ * Common return values for Codec2 operations.
+ */
+enum Status : int32_t {
+    /** Operation completed successfully. */
+    OK        = 0,
+
+    // bad input
+
+    /** Argument has invalid value (user error). */
+    BAD_VALUE = -22,
+    /** Argument uses invalid index (user error). */
+    BAD_INDEX = -75,
+    /** Argument/Index is valid but not possible. */
+    CANNOT_DO = -2147483646,
+
+    // bad sequencing of events
+
+    /** Object already exists. */
+    DUPLICATE = -17,
+    /** Object not found. */
+    NOT_FOUND = -2,
+    /** Operation is not permitted in the current state. */
+    BAD_STATE = -38,
+    /** Operation would block but blocking is not permitted. */
+    BLOCKING  = -9930,
+
+    // bad environment
+
+    /** Not enough memory to complete operation. */
+    NO_MEMORY = -12,
+    /** Missing permission to complete operation. */
+    REFUSED   = -1,
+
+    /** Operation did not complete within timeout. */
+    TIMED_OUT = -110,
+
+    // missing functionality
+
+    /** Operation is not implemented/supported (optional only). */
+    OMITTED   = -74,
+
+    // unknown fatal
+
+    /** Some unexpected error prevented the operation. */
+    CORRUPTED = -2147483648,
+
+    // uninitialized
+
+    /** Status has not been initialized. */
+    NO_INIT   = -19,
+};
+
+/**
+ * C2Param structure index.
+ *
+ * This is a number that is unique for each C2Param structure type.
+ *
+ * @sa Codec 2.0 standard.
+ */
+typedef uint32_t ParamIndex;
+
+/**
+ * Flattened representation of C2Param objects.
+ *
+ * The `Params` type is an array of bytes made up by concatenating a list of
+ * C2Param objects. The start index (offset into @ref Params) of each C2Param
+ * object in the list is divisible by 8. Up to 7 padding bytes may be added
+ * after each C2Param object to achieve this 64-bit alignment.
+ *
+ * Each C2Param object has the following layout:
+ * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
+ *   type of the C2Param object.
+ * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
+ * - (size - 8) bytes: data of the C2Param object.
+ *
+ * In order to interpret each C2Param object correctly, its structure must be
+ * described by IComponentStore::getStructDescriptors().
+ *
+ * @note Please refer to the Codec 2.0 standard for the list of standard
+ * parameter structures.
+ *
+ * @sa Codec 2.0 standard.
+ */
+typedef vec<uint8_t> Params;
+
+/**
+ * Identifying information of a field relative to a known C2Param structure.
+ *
+ * Within a given C2Param structure, each field is uniquely identified by @ref
+ * FieldId.
+ */
+struct FieldId {
+    /** Offset of the field in bytes. */
+    uint32_t offset;
+    /** Size of the field in bytes. */
+    uint32_t size;
+};
+
+/**
+ * Reference to a field in a C2Param structure.
+ */
+struct ParamField {
+    /** Index of the C2Param structure. */
+    ParamIndex index;
+    /** Identifier of the field inside the C2Param structure. */
+    FieldId fieldId;
+};
+
+/**
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
+ */
+struct ParamDescriptor {
+    /**
+     * Index of the C2Param structure being described.
+     */
+    ParamIndex index;
+
+    enum Attrib : uint32_t {
+        /**
+         * The parameter is required to be specified.
+         */
+        REQUIRED   = 1u << 0,
+        /**
+         * The parameter retains its value.
+         */
+        PERSISTENT = 1u << 1,
+        /**
+         * The parameter is strict.
+         */
+        STRICT     = 1u << 2,
+        /**
+         * The parameter is publicly read-only.
+         */
+        READ_ONLY  = 1u << 3,
+        /**
+         * The parameter must not be visible to clients.
+         */
+        HIDDEN     = 1u << 4,
+        /**
+         * The parameter must not be used by framework (other than testing).
+         */
+        INTERNAL   = 1u << 5,
+        /**
+         * The parameter is publicly constant (hence read-only).
+         */
+        CONST      = 1u << 6,
+    };
+    bitfield<Attrib> attrib;
+
+    /**
+     * Name of the structure. This must be unique for each structure.
+     */
+    string name;
+
+    /**
+     * Indices of other C2Param structures that this C2Param structure depends
+     * on.
+     */
+    vec<ParamIndex> dependencies;
+};
+
+// Generic way to describe supported numeric values for Codec2 interfaces.
+
+/**
+ * An untyped value that can fit in 64 bits, the type of which is communicated
+ * via a separate channel (@ref FieldSupportedValues.type).
+ */
+typedef uint64_t PrimitiveValue;
+
+/*
+ * Description of supported values for a field.
+ *
+ * This can be a continuous range or a discrete set of values.
+ */
+struct FieldSupportedValues {
+    /**
+     * Used if #type is `RANGE`.
+     *
+     * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
+     * structure represents a closed interval bounded by `min` and `max`.
+     *
+     * Otherwise, the #Range structure represents a finite sequence of numbers
+     * produced from the following recurrence relation:
+     *
+     * @code
+     * v[0] = min
+     * v[i] = v[i - 1] * num / denom + step ; i >= 1
+     * @endcode
+     *
+     * Both the ratio `num / denom` and the value `step` must be positive. The
+     * last number in the sequence described by this #Range structure is the
+     * largest number in the sequence that is smaller than or equal to `max`.
+     *
+     * @note
+     * The division in the formula may truncate the result if the data type of
+     * these values is an integral type.
+     */
+    struct Range {
+        /**
+         * Lower end of the range (inclusive).
+         */
+        PrimitiveValue min;
+        /**
+         * Upper end of the range (inclusive).
+         */
+        PrimitiveValue max;
+        /**
+         * The non-homogeneous term in the recurrence relation.
+         */
+        PrimitiveValue step;
+        /**
+         * The numerator of the scale coefficient in the recurrence relation.
+         */
+        PrimitiveValue num;
+        /**
+         * The denominator of the scale coefficient in the recurrence relation.
+         */
+        PrimitiveValue denom;
+    };
+
+    enum Type : int32_t {
+        /** No supported values */
+        EMPTY = 0,
+        /** Numeric range, described in a #Range structure */
+        RANGE,
+        /** List of values */
+        VALUES,
+        /** List of flags that can be OR-ed */
+        FLAGS,
+    };
+    /**
+     * Type of the supported values.
+     */
+    Type type;
+
+    /**
+     * When #type is #Type.RANGE, #range shall specify the range of possible
+     * values.
+     *
+     * The intended type of members of #range shall be clear in the context
+     * where `FieldSupportedValues` is used.
+     */
+    Range range;
+
+    /**
+     * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported
+     * values/flags.
+     *
+     * The intended type of components of #value shall be clear in the context
+     * where `FieldSupportedValues` is used.
+     */
+    vec<PrimitiveValue> values;
+};
+
+/**
+ * Supported values for a field.
+ *
+ * This is a pair of the field specifier together with an optional supported
+ * values object. This structure is used when reporting parameter configuration
+ * failures and conflicts.
+ */
+struct ParamFieldValues {
+    /**
+     * Reference to a field or a C2Param structure.
+     */
+    ParamField paramOrField;
+
+    /**
+     * Optional supported values for the field if #paramOrField specifies an
+     * actual field that is numeric (non struct, blob or string). Supported
+     * values for arrays (including string and blobs) describe the supported
+     * values for each element (character for string, and bytes for blobs). It
+     * is optional for read-only strings and blobs.
+     */
+    vec<FieldSupportedValues> values;
+};
+
+/**
+ * Description of a field inside a C2Param structure.
+ */
+struct FieldDescriptor {
+
+    /** Location of the field in the C2Param structure */
+    FieldId fieldId;
+
+    /**
+     * Possible types of the field.
+     */
+    enum Type : uint32_t {
+        NO_INIT = 0,
+        INT32,
+        UINT32,
+        CNTR32,
+        INT64,
+        UINT64,
+        CNTR64,
+        FLOAT,
+        /**
+         * Fixed-size string (POD).
+         */
+        STRING = 0x100,
+        /**
+         * A blob has no sub-elements and can be thought of as an array of
+         * bytes. However, bytes cannot be individually addressed by clients.
+         */
+        BLOB,
+        /**
+         * The field is a structure that may contain other fields.
+         */
+        STRUCT = 0x20000,
+    };
+    /**
+     * Type of the field.
+     */
+    bitfield<Type> type;
+
+    /**
+     * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+     * otherwise, #structIndex is not used.
+     */
+    ParamIndex structIndex;
+
+    /**
+     * Extent of the field.
+     * - For a non-array field, #extent is 1.
+     * - For a fixed-length array field, #extent is the length. An array field
+     *   of length 1 is indistinguishable from a non-array field.
+     * - For a variable-length array field, #extent is 0. This can only occur as
+     *   the last member of a C2Param structure.
+     */
+    uint32_t extent;
+
+    /**
+     * Name of the field. This must be unique for each field in the same
+     * structure.
+     */
+    string name;
+
+    /**
+     * Named value type. This is used for defining an enum value for a numeric
+     * type.
+     */
+    struct NamedValue {
+        /**
+         * Name of the enum value. This must be unique for each enum value in
+         * the same field.
+         */
+        string name;
+        /**
+         * Underlying value of the enum value. Multiple enum names may have the
+         * same underlying value.
+         */
+        PrimitiveValue value;
+    };
+    /**
+     * List of enum values. This is not used when #type is not one of the
+     * numeric types.
+     */
+    vec<NamedValue> namedValues;
+};
+
+/**
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
+ */
+struct StructDescriptor {
+    /**
+     * Index of the structure.
+     */
+    ParamIndex type;
+    /**
+     * List of fields in the structure.
+     *
+     * Fields are ordered by their offsets. A field that is a structure is
+     * ordered before its members.
+     */
+    vec<FieldDescriptor> fields;
+};
+
+/**
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
+ */
+struct SettingResult {
+    /** Failure code */
+    enum Failure : uint32_t {
+        /** Parameter is not supported. */
+        BAD_TYPE,
+        /** Parameter is not supported on the specific port. */
+        BAD_PORT,
+        /** Parameter is not supported on the specific stream. */
+        BAD_INDEX,
+        /** Parameter is read-only and cannot be set. */
+        READ_ONLY,
+        /** Parameter mismatches input data. */
+        MISMATCH,
+        /** Strict parameter does not accept value for the field at all. */
+        BAD_VALUE,
+        /**
+         * Strict parameter field value is in conflict with an/other
+         * setting(s).
+         */
+        CONFLICT,
+        /**
+         * Parameter field is out of range due to other settings. (This failure
+         * mode can only be used for strict calculated parameters.)
+         */
+        UNSUPPORTED,
+        /**
+         * Field does not access the requested parameter value at all. It has
+         * been corrected to the closest supported value. This failure mode is
+         * provided to give guidance as to what are the currently supported
+         * values for this field (which may be a subset of the at-all-potential
+         * values).
+         */
+        INFO_BAD_VALUE,
+        /**
+         * Requested parameter value is in conflict with an/other setting(s)
+         * and has been corrected to the closest supported value. This failure
+         * mode is given to provide guidance as to what are the currently
+         * supported values as well as to optionally provide suggestion to the
+         * client as to how to enable the requested parameter value.
+         */
+        INFO_CONFLICT,
+    };
+    Failure failure;
+
+    /**
+     * Failing (or corrected) field or parameter and optionally, currently
+     * supported values for the field. Values must only be set for field
+     * failures other than `BAD_VALUE`, and only if they are different from the
+     * globally supported values (e.g. due to restrictions by another parameter
+     * or input data).
+     */
+    ParamFieldValues field;
+
+    /**
+     * Conflicting parameters or fields with (optional) suggested values for any
+     * conflicting fields to avoid the conflict. Values must only be set for
+     * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
+     */
+    vec<ParamFieldValues> conflicts;
+};
+
+/**
+ * Ordering information of @ref FrameData objects. Each member is used for
+ * comparing urgency: a smaller difference from a reference value indicates that
+ * the associated Work object is more urgent. The reference value for each
+ * member is initialized the first time it is communicated between the client
+ * and the codec, and it may be updated to later values that are communicated.
+ *
+ * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
+ * order it represents is derived by subtracting the reference value, then
+ * interpreting the result as a signed number with the same storage size (using
+ * two's complement).
+ *
+ * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
+ * Codec 2.0 standard.
+ */
+struct WorkOrdinal {
+    /**
+     * Timestamp in microseconds.
+     */
+    uint64_t timestampUs;
+    /**
+     * Frame index.
+     */
+    uint64_t frameIndex;
+    /**
+     * Component specific frame ordinal.
+     */
+    uint64_t customOrdinal;
+};
+
+/**
+ * Storage type for `BaseBlock`.
+ *
+ * A `BaseBlock` is a representation of a codec memory block. Coded data,
+ * decoded data, codec-specific data, and other codec-related data are all sent
+ * in the form of BaseBlocks.
+ */
+safe_union BaseBlock {
+    /**
+     * #nativeBlock is the opaque representation of a buffer.
+     */
+    handle nativeBlock;
+    /**
+     * #pooledBlock is a reference to a buffer handled by a BufferPool.
+     */
+    BufferStatusMessage pooledBlock;
+};
+
+/**
+ * Reference to a @ref BaseBlock within a @ref WorkBundle.
+ *
+ * `Block` contains additional attributes that `BaseBlock` does not. These
+ * attributes may differ among `Block` objects that refer to the same
+ * `BaseBlock` in the same `WorkBundle`.
+ */
+struct Block {
+    /**
+     * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+     * #WorkBundle.baseBlocks.
+     */
+    uint32_t index;
+    /**
+     * Metadata associated with this `Block`.
+     */
+    Params meta;
+    /**
+     * Fence for synchronizing `Block` access.
+     */
+    handle fence;
+};
+
+/**
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
+ */
+struct Buffer {
+    /**
+     * Metadata associated with the buffer.
+     */
+    Params info;
+    /**
+     * Blocks contained in the buffer.
+     */
+    vec<Block> blocks;
+};
+
+/**
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
+ */
+struct InfoBuffer {
+    /**
+     * A C2Param structure index.
+     */
+    ParamIndex index;
+    /**
+     * Associated @ref Buffer object.
+     */
+    Buffer buffer;
+};
+
+/**
+ * Data for an input frame or an output frame.
+ *
+ * This structure represents a @e frame with its metadata. A @e frame consists
+ * of an ordered set of buffers, configuration changes, and info buffers along
+ * with some non-configuration metadata.
+ *
+ * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
+ * standard.
+ */
+struct FrameData {
+    enum Flags : uint32_t {
+        /**
+         * For input frames: no output frame shall be generated when processing
+         * this frame, but metadata must still be processed.
+         *
+         * For output frames: this frame must be discarded but metadata is still
+         * valid.
+         */
+        DROP_FRAME    = (1 << 0),
+        /**
+         * This frame is the last frame of the current stream. Further frames
+         * are part of a new stream.
+         */
+        END_OF_STREAM = (1 << 1),
+        /**
+         * This frame must be discarded with its metadata.
+         *
+         * This flag is only set by components, e.g. as a response to the flush
+         * command.
+         */
+        DISCARD_FRAME = (1 << 2),
+        /**
+         * This frame is not the last frame produced for the input.
+         *
+         * This flag is normally set by the component - e.g. when an input frame
+         * results in multiple output frames, this flag is set on all but the
+         * last output frame.
+         *
+         * Also, when components are chained, this flag should be propagated
+         * down the work chain. That is, if set on an earlier frame of a
+         * work-chain, it should be propagated to all later frames in that
+         * chain. Additionally, components down the chain could set this flag
+         * even if not set earlier, e.g. if multiple output frames are generated
+         * at that component for the input frame.
+         */
+        FLAG_INCOMPLETE = (1 << 3),
+        /**
+         * This frame contains only codec-specific configuration data, and no
+         * actual access unit.
+         *
+         * @deprecated Pass codec configuration with the codec-specific
+         * configuration info together with the access unit.
+         */
+        CODEC_CONFIG  = (1u << 31),
+    };
+
+    /**
+     * Frame flags, as described in #Flags.
+     */
+    bitfield<Flags> flags;
+
+    /**
+     * @ref WorkOrdinal of the frame.
+     */
+    WorkOrdinal ordinal;
+
+    /**
+     * List of frame buffers.
+     */
+    vec<Buffer> buffers;
+
+    /**
+     * List of configuration updates.
+     */
+    Params configUpdate;
+
+    /**
+     * List of info buffers.
+     */
+    vec<InfoBuffer> infoBuffers;
+};
+
+/**
+ * In/out structure containing some instructions for and results from output
+ * processing.
+ *
+ * This is a part of @ref Work. One `Worklet` corresponds to one output
+ * @ref FrameData. The client must construct an original `Worklet` object inside
+ * a @ref Work object for each expected output before calling
+ * IComponent::queue().
+ */
+struct Worklet {
+    /**
+     * Component id. (Input)
+     *
+     * This is used only when tunneling is enabled.
+     *
+     * When used, this must match the return value from IConfigurable::getId().
+     */
+    uint32_t componentId;
+
+    /**
+     * List of C2Param objects describing tunings to be applied before
+     * processing this `Worklet`. (Input)
+     */
+    Params tunings;
+
+    /**
+     * Flag determining whether this `Worklet` has output or not.
+     */
+    bool hasOutput;
+
+    /**
+     * List of failures. (Output)
+     */
+    vec<SettingResult> failures;
+
+    /**
+     * Output frame data. (Output)
+     */
+    FrameData output;
+};
+
+/**
+ * A collection of input data to and output data from the component.
+ *
+ * A `Work` object holds information about a single work item. It is created by
+ * the client and passed to the component via IComponent::queue(). The component
+ * has two ways of returning a `Work` object to the client:
+ *   1. If the queued `Work` object has been successfully processed,
+ *      IComponentListener::onWorkDone() shall be called to notify the listener,
+ *      and the output shall be included in the returned `Work` object.
+ *   2. If the client calls IComponent::flush(), a `Work` object that has not
+ *      been processed shall be returned.
+ *
+ * `Work` is a part of @ref WorkBundle.
+ */
+struct Work {
+    /**
+     * Additional work chain info not part of this work.
+     */
+    Params chainInfo;
+
+    /**
+     * @ref FrameData for the input.
+     */
+    FrameData input;
+
+    /**
+     * The chain of `Worklet`s.
+     *
+     * The length of #worklets is 1 when tunneling is not enabled.
+     *
+     * If #worklets has more than a single element, the tunnels between
+     * successive components of the work chain must have been successfully
+     * pre-registered at the time that the `Work` is submitted. Allocating the
+     * output buffers in the `Worklet`s is the responsibility of each component
+     * in the chain.
+     *
+     * Upon `Work` submission, #worklets must be an appropriately sized vector
+     * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
+     * successful processing, all but the final `Worklet` in the returned
+     * #worklets must have @ref Worklet.hasOutput set to `false`.
+     */
+    vec<Worklet> worklets;
+
+    /**
+     * The number of `Worklet`s successfully processed in this chain.
+     *
+     * This must be initialized to 0 by the client when the `Work` is submitted,
+     * and it must contain the number of `Worklet`s that were successfully
+     * processed when the `Work` is returned to the client.
+     *
+     * #workletsProcessed cannot exceed the length of #worklets. If
+     * #workletsProcessed is smaller than the length of #worklets, #result
+     * cannot be `OK`.
+     */
+    uint32_t workletsProcessed;
+
+    /**
+     * The final outcome of the `Work` (corresponding to #workletsProcessed).
+     *
+     * The value of @ref Status.OK implies that all `Worklet`s have been
+     * successfully processed.
+     */
+    Status result;
+};
+
+/**
+ * List of `Work` objects.
+ *
+ * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
+ * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
+ * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
+ * objects together provides two benefits:
+ *   1. Batching of `Work` objects can reduce the number of IPC calls.
+ *   2. If multiple `Work` objects contain `Block`s that refer to the same
+ *      `BaseBlock`, the number of `BaseBlock`s that is sent between processes
+ *      is also reduced.
+ *
+ * @note `WorkBundle` is the HIDL counterpart of the vector of `C2Work` in the
+ * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
+ * data transferred over an IPC.
+ */
+struct WorkBundle {
+    /**
+     * A list of Work items.
+     */
+    vec<Work> works;
+    /**
+     * A list of blocks indexed by elements of #works.
+     */
+    vec<BaseBlock> baseBlocks;
+};
+
+/**
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
+ */
+struct FieldSupportedValuesQuery {
+    /**
+     * Identity of the field to query.
+     */
+    ParamField field;
+
+    enum Type : uint32_t {
+        /** Query all possible values regardless of other settings. */
+        POSSIBLE,
+        /** Query currently possible values given dependent settings. */
+        CURRENT,
+    };
+    /**
+     * Type of the query. See #Type for more information.
+     */
+    Type type;
+};
+
+/**
+ * This structure is used to hold the result from
+ * IConfigurable::querySupportedValues().
+ */
+struct FieldSupportedValuesQueryResult {
+    /**
+     * Result of the query. Possible values are
+     * - `OK`: The query was successful.
+     * - `BAD_STATE`: The query was requested when the `IConfigurable` instance
+     *   was in a bad state.
+     * - `BAD_INDEX`: The requested field was not recognized.
+     * - `TIMED_OUT`: The query could not be completed in a timely manner.
+     * - `BLOCKING`: The query must block, but the parameter `mayBlock` in the
+     *   call to `querySupportedValues()` was `false`.
+     * - `CORRUPTED`: Some unknown error occurred.
+     */
+    Status status;
+
+    /**
+     * Supported values. This is meaningful only when #status is `OK`.
+     */
+    FieldSupportedValues values;
+};
+
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index 0050e52..a64268f 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -34,9 +34,11 @@
 namespace neuralnetworks {
 namespace V1_1 {
 
-using V1_0::Request;
 using V1_0::DeviceStatus;
 using V1_0::ErrorStatus;
+using V1_0::Operand;
+using V1_0::OperandType;
+using V1_0::Request;
 
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index e183a26..5a661e0 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -17,8 +17,11 @@
     ],
     types: [
         "Model",
+        "Operand",
+        "OperandType",
         "Operation",
         "OperationType",
     ],
     gen_java: false,
 }
+
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index 9cc23a2..aff4cf3 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -26,6 +26,36 @@
  */
 interface IDevice extends @1.1::IDevice {
     /**
+     * Get the version string of the driver implementation.
+     *
+     * The version string must be a unique token among the set of version strings of
+     * drivers of a specific device. The token identifies the device driver's
+     * implementation. The token must not be confused with the feature level which is solely
+     * defined by the interface version. This API is opaque to the Android framework, but the
+     * Android framework may use the information for debugging or to pass on to NNAPI applications.
+     *
+     * Application developers sometimes have specific requirements to ensure good user experiences,
+     * and they need more information to make intelligent decisions when the Android framework cannot.
+     * For example, combined with the device name and other information, the token can help
+     * NNAPI applications filter devices based on their needs:
+     *     - An application demands a certain level of performance, but a specific version of
+     *       the driver cannot meet that requirement because of a performance regression.
+     *       The application can blacklist the driver based on the version provided.
+     *     - An application has a minimum precision requirement, but certain versions of
+     *       the driver cannot meet that requirement because of bugs or certain optimizations.
+     *       The application can filter out versions of these drivers.
+     *
+     * @return status Error status returned from querying the version string. Must be:
+     *     - NONE if the query was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the query resulted in an
+     *       unspecified error
+     * @return version The version string of the device implementation.
+     *     Must have nonzero length
+     */
+    getVersionString() generates (ErrorStatus status, string version);
+
+    /**
      * Gets the supported operations in a model.
      *
      * getSupportedOperations indicates which operations of a model are fully
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index bed1d5c..4a1e7a8 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -16,10 +16,36 @@
 
 package android.hardware.neuralnetworks@1.2;
 
-import @1.0::Operand;
+import @1.0::DataLocation;
+import @1.0::OperandLifeTime;
+import @1.0::OperandType;
 import @1.0::PerformanceInfo;
 import @1.1::OperationType;
 
+enum OperandType : @1.0::OperandType {
+    /**
+     * An 8 bit boolean scalar value.
+     *
+     * Values of this operand type are either true or false. A zero value
+     * represents false; any other value represents true.
+     */
+    BOOL = 6,
+    /**
+     * A tensor of 16 bit signed integers that represent real numbers.
+     *
+     * Attached to this tensor are two numbers that are used to convert the 16
+     * bit integer to the real value and vice versa. These two numbers are:
+     * - scale: a 32 bit floating point value greater than zero.
+     * - zeroPoint: a 32 bit integer, in range [-32768, 32767].
+     *
+     * The formula is:
+     * realValue = (integerValue - zeroPoint) * scale.
+     */
+    TENSOR_QUANT16_ASYMM = 7,
+    /** A tensor of 16 bit floating point values. */
+    TENSOR_FLOAT16 = 8,
+};
+
 /**
  * Operation types.
  *
@@ -102,6 +128,101 @@
 };
 
 /**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * Data type of the operand.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     *
+     * For a scalar operand, dimensions.size() must be 0.
+     *
+     * For a tensor operand, dimensions.size() must be at least 1;
+     * however, any of the dimensions may be unspecified.
+     *
+     * A tensor operand with all dimensions specified has "fully
+     * specified" dimensions. Whenever possible (i.e., whenever the
+     * dimensions are known at model construction time), a tensor
+     * operand should have (but is not required to have) fully
+     * specified dimensions, in order to enable the best possible
+     * performance.
+     *
+     * If a tensor operand's dimensions are not fully specified, the
+     * dimensions of the operand are deduced from the operand
+     * dimensions and values of the operation for which that operand
+     * is an output.
+     *
+     * In the following situations, a tensor operand's dimensions must
+     * be fully specified:
+     *
+     *     . The operand has lifetime CONSTANT_COPY or
+     *       CONSTANT_REFERENCE.
+     *
+     *     . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+     *       specified dimensions must either be present in the
+     *       Operand or they must be provided in the corresponding
+     *       RequestArgument.
+     *       EXCEPTION: If the input or output is optional and omitted
+     *       (by setting the hasNoValue field of the corresponding
+     *       RequestArgument to true) then it need not have fully
+     *       specified dimensions.
+     *
+     * A tensor operand with some number of unspecified dimensions is
+     * represented by setting each unspecified dimension to 0.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of times this operand appears as an operation input.
+     *
+     * (For example, if this operand appears once in one operation's
+     * input list, and three times in another operation's input list,
+     * then numberOfConsumers = 4.)
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+     * TENSOR_INT32.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+     * NO_VALUE:
+     * - All the fields must be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+};
+
+/**
  * A Neural Network Model.
  *
  * This includes not only the execution graph, but also constant data such as
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index d2dea1d..eb3ebd3 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -37,6 +37,14 @@
     EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
 }
 
+// device version test
+TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) {
+    Return<void> ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) {
+        EXPECT_EQ(ErrorStatus::NONE, status);
+        EXPECT_LT(0, version.size());
+    });
+    EXPECT_TRUE(ret.isOk());
+}
 }  // namespace functional
 }  // namespace vts
 }  // namespace V1_2
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 7ec6ff1..b840199 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -26,9 +26,7 @@
 namespace V1_2 {
 
 using V1_0::IPreparedModel;
-using V1_0::Operand;
 using V1_0::OperandLifeTime;
-using V1_0::OperandType;
 using V1_1::ExecutionPreference;
 
 namespace vts {
@@ -131,10 +129,10 @@
 ///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
 
 static const int32_t invalidOperandTypes[] = {
-    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
-    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
-    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
-    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+    static_cast<int32_t>(OperandType::FLOAT32) - 1,               // lower bound fundamental
+    static_cast<int32_t>(OperandType::TENSOR_QUANT16_ASYMM) + 1,  // upper bound fundamental
+    static_cast<int32_t>(OperandType::OEM) - 1,                   // lower bound OEM
+    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,       // upper bound OEM
 };
 
 static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
@@ -157,10 +155,13 @@
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
+        case OperandType::BOOL:
             return 1;
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_INT32:
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_ASYMM:
             return 0;
         default:
             return 0;
@@ -185,11 +186,14 @@
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
+        case OperandType::BOOL:
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
             return 1.0f;
         case OperandType::TENSOR_INT32:
             return -1.0f;
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_ASYMM:
             return 0.0f;
         default:
             return 0.0f;
@@ -214,10 +218,13 @@
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
+        case OperandType::BOOL:
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_INT32:
             return {1};
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_ASYMM:
             return {-1, 256};
         default:
             return {};
@@ -253,10 +260,12 @@
         case OperandType::FLOAT32:
         case OperandType::INT32:
         case OperandType::UINT32:
+        case OperandType::BOOL:
             newOperand.dimensions = hidl_vec<uint32_t>();
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
                 operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
@@ -269,6 +278,7 @@
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_ASYMM:
             newOperand.dimensions =
                 operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
new file mode 100644
index 0000000..2f16a21
--- /dev/null
+++ b/power/stats/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.power.stats@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IPowerStats.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Status",
+        "RailInfo",
+        "EnergyData",
+    ],
+    gen_java: false,
+}
+
diff --git a/power/stats/1.0/IPowerStats.hal b/power/stats/1.0/IPowerStats.hal
new file mode 100644
index 0000000..d75e170
--- /dev/null
+++ b/power/stats/1.0/IPowerStats.hal
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.power.stats@1.0;
+
+interface IPowerStats {
+
+    /**
+     * Rail information:
+     * Reports information related to the rails being monitored.
+     *
+     * @return rails Information about monitored rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getRailInfo()
+        generates(vec<RailInfo> rails, Status status);
+
+    /**
+     * Rail level energy measurements for low frequency clients:
+     * Reports accumulated energy since boot on each rail.
+     *
+     * @param railIndices Indices of rails for which data is required.
+     *     To get data for all rails pass an empty vector. Rail name to
+     *     index mapping can be queried from getRailInfo() API.
+     * @return data Energy values since boot for all requested rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getEnergyData(vec<uint32_t> railIndices)
+        generates(vec<EnergyData> data, Status status);
+
+    /**
+     * Stream rail level power measurements for high frequency clients:
+     * Streams accumulated energy since boot on each rail. This API is
+     * asynchronous.
+     *
+     * @param timeMs Time(in ms) for which energyData should be streamed
+     * @return mqDesc Unsynchronous Fast Message Queue descriptor - One
+     *     writer(power.stats HAL) multiple readers are supported. Reader
+     *     should read faster than writer otherwise data might be
+     *     overwritten. Data is present in following format in the queue:
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- 1st Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *     |          .            |
+     *     |          .            |
+     *     |          .            |
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- kth Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *
+     *     where,
+     *     n = railsPerSample
+     *     k = numSamples
+     *
+     * @return numSamples Number of samples which will be generated in timeMs.
+     * @return railsPerSample Number of rails measured per sample.
+     * @return status SUCCESS on success or FILESYSTEM_ERROR on filesystem
+     *     nodes access or NOT_SUPPORTED if feature is not enabled.
+     */
+    streamEnergyData(uint32_t timeMs)
+        generates(fmq_unsync<EnergyData> mqDesc, uint32_t numSamples,
+                uint32_t railsPerSample, Status status);
+};
diff --git a/power/stats/1.0/types.hal b/power/stats/1.0/types.hal
new file mode 100644
index 0000000..826c29b
--- /dev/null
+++ b/power/stats/1.0/types.hal
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.power.stats@1.0;
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+    NOT_SUPPORTED = 1,
+    INVALID_INPUT = 2,
+    FILESYSTEM_ERROR = 3,
+};
+
+struct RailInfo {
+    /** Index corresponding to the rail */
+    uint32_t index;
+    /** Name of the rail */
+    string railName;
+    /** Name of the subsystem to which this rail belongs */
+    string subsysName;
+    /** Hardware sampling rate */
+    uint32_t samplingRate;
+};
+
+struct EnergyData {
+    /**
+     * Index corrensponding to the rail. This index matches
+     * the index returned in RailInfo
+     */
+    uint32_t index;
+    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    uint64_t timestamp;
+    /** Accumulated energy since device boot in microwatt-seconds (uWs) */
+    uint64_t energy;
+};
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index 9424a85..b6610e0 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -17,9 +17,11 @@
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.2",
         "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
     ],
     types: [
         "AccessNetwork",
+        "DataProfileInfo",
         "DataRegStateResult",
         "EmergencyNumber",
         "EmergencyNumberSource",
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
index 2b14488..dde9d71 100644
--- a/radio/1.3/IRadio.hal
+++ b/radio/1.3/IRadio.hal
@@ -16,7 +16,7 @@
 
 package android.hardware.radio@1.3;
 
-import @1.0::DataProfileInfo;
+import @1.3::DataProfileInfo;
 import @1.0::Dial;
 import @1.2::DataRequestReason;
 import @1.2::IRadio;
@@ -56,13 +56,7 @@
      * @param accessNetwork The access network to setup the data call. If the data connection cannot
      *     be established on the specified access network, the setup request must be failed.
      * @param dataProfileInfo Data profile info.
-     * @param modemCognitive Indicates that the requested profile has previously been provided via
-     *     setDataProfile().
      * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
-     * @param isRoaming Indicates whether or not the framework has requested this setupDataCall for
-     *     a roaming network. The 'protocol' parameter in the old RIL API must be filled
-     *     accordingly based on the roaming condition. Note this is for backward compatibility with
-     *     the old radio modem. The modem must not use this param for any other reason.
      * @param reason The request reason. Must be DataRequestReason.NORMAL or
      *     DataRequestReason.HANDOVER.
      * @param addresses If the reason is DataRequestReason.HANDOVER, this indicates the list of link
@@ -82,8 +76,28 @@
      * Note this API is same as 1.2 version except using the 1.3 AccessNetwork as the input param.
      */
     oneway setupDataCall_1_3(int32_t serial, AccessNetwork accessNetwork,
-            DataProfileInfo dataProfileInfo, bool modemCognitive, bool roamingAllowed,
-            bool isRoaming, DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+            DataProfileInfo dataProfileInfo, bool roamingAllowed,
+            DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+    /**
+     * Set an apn to initial attach network
+     *
+     * @param serial Serial number of request.
+     * @param dataProfileInfo data profile containing APN settings
+     *
+     * Response callback is IRadioResponse.setInitialAttachApnResponse()
+     */
+    oneway setInitialAttachApn_1_3(int32_t serial, DataProfileInfo dataProfileInfo);
+
+    /**
+     * Send data profiles of the current carrier to the modem.
+     *
+     * @param serial Serial number of request.
+     * @param profiles Array of DataProfile to set.
+     *
+     * Response callback is IRadioResponse.setDataProfileResponse()
+     */
+    oneway setDataProfile_1_3(int32_t serial, vec<DataProfileInfo> profiles);
 
     /**
      * Initiate emergency voice call, with zero or more emergency service category(s).
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
index 09202a5..8b0891c 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -16,11 +16,18 @@
 
 package android.hardware.radio@1.3;
 
+import @1.0::ApnAuthType;
+import @1.0::ApnTypes;
+import @1.0::DataProfileId;
+import @1.0::DataProfileInfoType;
+import @1.0::RadioAccessFamily;
 import @1.0::RegState;
 import @1.2::AccessNetwork;
 import @1.2::CellIdentity;
 import @1.2::DataRegStateResult;
 
+import android.hidl.safe_union@1.0::Monostate;
+
 enum AccessNetwork : @1.2::AccessNetwork {
     /**
      * Unknown access network
@@ -157,6 +164,82 @@
      * will be empty when device is camped only on 2G/3G .
      */
     safe_union VopsInfo {
+        Monostate noinit;
+
         LteVopsInfo lteVopsInfo; // LTE network capability
     } vopsInfo;
 };
+
+/**
+ * Overwritten from @1.0::DataProfileInfo in order to deprecate 'mvnoType', and 'mvnoMatchData'.
+ * In the future, this must be extended instead of overwritten.
+ * Also added 'preferred' and 'persistent' in this version.
+ */
+struct DataProfileInfo {
+    /** id of the data profile */
+    DataProfileId profileId;
+
+    /** The APN name */
+    string apn;
+
+    /**
+     * One of the PDP_type values in TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6",
+     * or "PPP".
+     */
+    string protocol;
+
+    /**
+     * one of the PDP_type values in TS 27.007 section 10.1.1 used on roaming network. For example,
+     * "IP", "IPV6", "IPV4V6", or "PPP".
+     */
+    string roamingProtocol;
+
+    /** APN authentication type */
+    ApnAuthType authType;
+
+    /** The username for APN, or empty string */
+    string user;
+
+    /** The password for APN, or empty string */
+    string password;
+
+    /** Data profile technology type */
+    DataProfileInfoType type;
+
+    /** The period in seconds to limit the maximum connections */
+    int32_t maxConnsTime;
+
+    /** The maximum connections during maxConnsTime */
+    int32_t maxConns;
+
+    /**
+     * 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.
+     */
+    int32_t waitTime;
+
+    /** True to enable the profile, false to disable */
+    bool enabled;
+
+    /** Supported APN types bitmap. See ApnTypes for the value of each bit. */
+    bitfield<ApnTypes> supportedApnTypesBitmap;
+
+    /** The bearer bitmap. See RadioAccessFamily for the value of each bit. */
+    bitfield<RadioAccessFamily> bearerBitmap;
+
+    /** Maximum transmission unit (MTU) size in bytes */
+    int32_t mtu;
+
+    /**
+     * True if this data profile was used to bring up the last default (i.e internet) data
+     * connection successfully.
+     */
+    bool preferred;
+
+    /**
+     * If true, modem must persist this data profile and profileId must not be
+     * set to DataProfileId.INVALID. If the same data profile exists, this data profile must
+     * overwrite it.
+     */
+    bool persistent;
+};
diff --git a/sensors/1.0/default/convert.cpp b/sensors/1.0/default/convert.cpp
index a5747d4..52f5e4f 100644
--- a/sensors/1.0/default/convert.cpp
+++ b/sensors/1.0/default/convert.cpp
@@ -74,8 +74,7 @@
     };
 
     switch (dst->sensorType) {
-        case SensorType::META_DATA:
-        {
+        case SensorType::META_DATA: {
             dst->u.meta.what = (MetaDataEventType)src.meta_data.what;
             // Legacy HALs contain the handle reference in the meta data field.
             // Copy that over to the handle of the event. In legacy HALs this
@@ -89,8 +88,7 @@
         case SensorType::ORIENTATION:
         case SensorType::GYROSCOPE:
         case SensorType::GRAVITY:
-        case SensorType::LINEAR_ACCELERATION:
-        {
+        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;
@@ -98,10 +96,7 @@
             break;
         }
 
-        case SensorType::ROTATION_VECTOR:
-        case SensorType::GAME_ROTATION_VECTOR:
-        case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
-        {
+        case SensorType::GAME_ROTATION_VECTOR: {
             dst->u.vec4.x = src.data[0];
             dst->u.vec4.y = src.data[1];
             dst->u.vec4.z = src.data[2];
@@ -109,151 +104,150 @@
             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::ROTATION_VECTOR:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+            dst->u.data[0] = src.data[0];
+            dst->u.data[1] = src.data[1];
+            dst->u.data[2] = src.data[2];
+            dst->u.data[3] = src.data[3];
+            dst->u.data[4] = src.data[4];
+            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:
-      case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-      {
-          dst->u.scalar = src.data[0];
-          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::STEP_COUNTER:
-      {
-          dst->u.stepCount = src.u64.step_counter;
-          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:
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT: {
+            dst->u.scalar = src.data[0];
+            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::STEP_COUNTER: {
+            dst->u.stepCount = src.u64.step_counter;
+            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::HEART_RATE: {
+            dst->u.heartRate.bpm = src.heart_rate.bpm;
+            dst->u.heartRate.status = (SensorStatus)src.heart_rate.status;
+            break;
+        }
 
-      case SensorType::DYNAMIC_SENSOR_META:
-      {
-          dst->u.dynamic.connected = src.dynamic_sensor_meta.connected;
-          dst->u.dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
+        case SensorType::POSE_6DOF: {  // 15 floats
+            for (size_t i = 0; i < 15; ++i) {
+                dst->u.pose6DOF[i] = src.data[i];
+            }
+            break;
+        }
 
-          memcpy(dst->u.dynamic.uuid.data(),
-                 src.dynamic_sensor_meta.uuid,
-                 16);
+        case SensorType::DYNAMIC_SENSOR_META: {
+            dst->u.dynamic.connected = src.dynamic_sensor_meta.connected;
+            dst->u.dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
 
-          break;
-      }
+            memcpy(dst->u.dynamic.uuid.data(), src.dynamic_sensor_meta.uuid, 16);
 
-      case SensorType::ADDITIONAL_INFO:
-      {
-          ::android::hardware::sensors::V1_0::AdditionalInfo *dstInfo =
-              &dst->u.additional;
+            break;
+        }
 
-          const additional_info_event_t &srcInfo = src.additional_info;
+        case SensorType::ADDITIONAL_INFO: {
+            ::android::hardware::sensors::V1_0::AdditionalInfo* dstInfo = &dst->u.additional;
 
-          dstInfo->type =
-              (::android::hardware::sensors::V1_0::AdditionalInfoType)
-                  srcInfo.type;
+            const additional_info_event_t& srcInfo = src.additional_info;
 
-          dstInfo->serial = srcInfo.serial;
+            dstInfo->type = (::android::hardware::sensors::V1_0::AdditionalInfoType)srcInfo.type;
 
-          CHECK_EQ(sizeof(dstInfo->u), sizeof(srcInfo.data_int32));
-          memcpy(&dstInfo->u, srcInfo.data_int32, sizeof(srcInfo.data_int32));
-          break;
-      }
+            dstInfo->serial = srcInfo.serial;
 
-      default:
-      {
-          CHECK_GE((int32_t)dst->sensorType,
-                   (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+            CHECK_EQ(sizeof(dstInfo->u), sizeof(srcInfo.data_int32));
+            memcpy(&dstInfo->u, srcInfo.data_int32, sizeof(srcInfo.data_int32));
+            break;
+        }
 
-          memcpy(dst->u.data.data(), src.data, 16 * sizeof(float));
-          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),
-      .sensor = src.sensorHandle,
-      .type = (int32_t)src.sensorType,
-      .reserved0 = 0,
-      .timestamp = src.timestamp
-  };
+    *dst = {.version = sizeof(sensors_event_t),
+            .sensor = src.sensorHandle,
+            .type = (int32_t)src.sensorType,
+            .reserved0 = 0,
+            .timestamp = src.timestamp};
 
-  switch (src.sensorType) {
-      case SensorType::META_DATA:
-      {
-          // Legacy HALs expect the handle reference in the meta data field.
-          // Copy it over from the handle of the event.
-          dst->meta_data.what = (int32_t)src.u.meta.what;
-          dst->meta_data.sensor = src.sensorHandle;
-          // Set the sensor handle to 0 to maintain compatibility.
-          dst->sensor = 0;
-          break;
-      }
+    switch (src.sensorType) {
+        case SensorType::META_DATA: {
+            // Legacy HALs expect the handle reference in the meta data field.
+            // Copy it over from the handle of the event.
+            dst->meta_data.what = (int32_t)src.u.meta.what;
+            dst->meta_data.sensor = src.sensorHandle;
+            // Set the sensor handle to 0 to maintain compatibility.
+            dst->sensor = 0;
+            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::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::GAME_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::ROTATION_VECTOR:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+            dst->data[0] = src.u.data[0];
+            dst->data[1] = src.u.data[1];
+            dst->data[2] = src.u.data[2];
+            dst->data[3] = src.u.data[3];
+            dst->data[4] = src.u.data[4];
+            break;
+        }
+
+        case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
         case SensorType::GYROSCOPE_UNCALIBRATED:
         case SensorType::ACCELEROMETER_UNCALIBRATED:
         {
@@ -283,35 +277,30 @@
         case SensorType::STATIONARY_DETECT:
         case SensorType::MOTION_DETECT:
         case SensorType::HEART_BEAT:
-        case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-        {
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT: {
             dst->data[0] = src.u.scalar;
             break;
         }
 
-        case SensorType::STEP_COUNTER:
-        {
+        case SensorType::STEP_COUNTER: {
             dst->u64.step_counter = src.u.stepCount;
             break;
         }
 
-        case SensorType::HEART_RATE:
-        {
+        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
-        {
+        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:
-        {
+        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
@@ -323,8 +312,7 @@
             break;
         }
 
-        case SensorType::ADDITIONAL_INFO:
-        {
+        case SensorType::ADDITIONAL_INFO: {
             const ::android::hardware::sensors::V1_0::AdditionalInfo &srcInfo =
                 src.u.additional;
 
@@ -341,8 +329,7 @@
             break;
         }
 
-        default:
-        {
+        default: {
             CHECK_GE((int32_t)src.sensorType,
                      (int32_t)SensorType::DEVICE_PRIVATE_BASE);
 
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 0ea400e..6563e3c 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -18,13 +18,14 @@
     name: "VtsHalSensorsV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "GrallocWrapper.cpp",
+        "SensorsHidlEnvironmentV1_0.cpp",
         "VtsHalSensorsV1_0TargetTest.cpp"
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.sensors@1.0",
+        "VtsHalSensorsTargetTestUtils",
     ],
 }
 
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.cpp b/sensors/1.0/vts/functional/GrallocWrapper.cpp
deleted file mode 100644
index e422d62..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocWrapper"
-
-#include "GrallocWrapper.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-GrallocWrapper::GrallocWrapper() { init(); }
-
-void GrallocWrapper::init() {
-  mAllocator = allocator2::IAllocator::getService();
-  if (mAllocator == nullptr) {
-    ALOGE("Failed to get allocator service");
-  }
-
-  mMapper = mapper2::IMapper::getService();
-  if (mMapper == nullptr) {
-    ALOGE("Failed to get mapper service");
-  }
-  if (mMapper->isRemote()) {
-    ALOGE("Mapper is not in passthrough mode");
-  }
-}
-
-GrallocWrapper::~GrallocWrapper() {
-  for (auto bufferHandle : mClonedBuffers) {
-    auto buffer = const_cast<native_handle_t*>(bufferHandle);
-    native_handle_close(buffer);
-    native_handle_delete(buffer);
-  }
-  mClonedBuffers.clear();
-
-  for (auto bufferHandle : mImportedBuffers) {
-    auto buffer = const_cast<native_handle_t*>(bufferHandle);
-    if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
-      ALOGE("Failed to free buffer %p", buffer);
-    }
-  }
-  mImportedBuffers.clear();
-}
-
-sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
-  return mAllocator;
-}
-
-std::string GrallocWrapper::dumpDebugInfo() {
-  std::string debugInfo;
-  mAllocator->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-const native_handle_t* GrallocWrapper::cloneBuffer(
-    const hardware::hidl_handle& rawHandle) {
-  const native_handle_t* bufferHandle =
-      native_handle_clone(rawHandle.getNativeHandle());
-
-  if (bufferHandle) {
-    mClonedBuffers.insert(bufferHandle);
-  }
-  return bufferHandle;
-}
-
-std::vector<const native_handle_t*> GrallocWrapper::allocate(
-    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import,
-    uint32_t* outStride) {
-  std::vector<const native_handle_t*> bufferHandles;
-  bufferHandles.reserve(count);
-  mAllocator->allocate(
-      descriptor, count,
-      [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
-        if (mapper2::Error::NONE != tmpError) {
-          ALOGE("Failed to allocate buffers");
-        }
-        if (count != tmpBuffers.size()) {
-          ALOGE("Invalid buffer array");
-        }
-
-        for (uint32_t i = 0; i < count; i++) {
-          if (import) {
-            bufferHandles.push_back(importBuffer(tmpBuffers[i]));
-          } else {
-            bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
-          }
-        }
-
-        if (outStride) {
-          *outStride = tmpStride;
-        }
-      });
-
-  return bufferHandles;
-}
-
-const native_handle_t* GrallocWrapper::allocate(
-    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
-    uint32_t* outStride) {
-  mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
-  ALOGE("QQ");
-  auto buffers = allocate(descriptor, 1, import, outStride);
-  return buffers[0];
-}
-
-sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; }
-
-mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
-    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
-  mapper2::BufferDescriptor descriptor;
-  mMapper->createDescriptor(
-      descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
-        if (tmpError != mapper2::Error::NONE) {
-          ALOGE("Failed to create descriptor");
-        }
-        descriptor = tmpDescriptor;
-      });
-
-  return descriptor;
-}
-
-const native_handle_t* GrallocWrapper::importBuffer(
-    const hardware::hidl_handle& rawHandle) {
-  const native_handle_t* bufferHandle = nullptr;
-  mMapper->importBuffer(
-      rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
-        if (tmpError != mapper2::Error::NONE) {
-          ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
-        }
-        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
-      });
-
-  if (bufferHandle) {
-    mImportedBuffers.insert(bufferHandle);
-  }
-
-  return bufferHandle;
-}
-
-void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  if (mImportedBuffers.erase(bufferHandle)) {
-    mapper2::Error error = mMapper->freeBuffer(buffer);
-    if (error != mapper2::Error::NONE) {
-      ALOGE("Failed to free %p", buffer);
-    }
-  } else {
-    mClonedBuffers.erase(bufferHandle);
-    native_handle_close(buffer);
-    native_handle_delete(buffer);
-  }
-}
-
-void* GrallocWrapper::lock(const native_handle_t* bufferHandle,
-                           uint64_t cpuUsage,
-                           const mapper2::IMapper::Rect& accessRegion,
-                           int acquireFence) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-  hardware::hidl_handle acquireFenceHandle;
-  if (acquireFence >= 0) {
-    auto h = native_handle_init(acquireFenceStorage, 1, 0);
-    h->data[0] = acquireFence;
-    acquireFenceHandle = h;
-  }
-
-  void* data = nullptr;
-  mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                [&](const auto& tmpError, const auto& tmpData) {
-                  if (tmpError != mapper2::Error::NONE) {
-                    ALOGE("Failed to lock buffer %p", buffer);
-                  }
-                  data = tmpData;
-                });
-
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
-
-  return data;
-}
-
-int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  int releaseFence = -1;
-  mMapper->unlock(buffer, [&](const auto& tmpError,
-                              const auto& tmpReleaseFence) {
-    if (tmpError != mapper2::Error::NONE) {
-      ALOGE("Failed to unlock buffer %p", buffer);
-    }
-
-    auto fenceHandle = tmpReleaseFence.getNativeHandle();
-    if (fenceHandle) {
-      if (fenceHandle->numInts != 0) {
-        ALOGE("Invalid fence handle %p", fenceHandle);
-      }
-      if (fenceHandle->numFds == 1) {
-        releaseFence = dup(fenceHandle->data[0]);
-        if (releaseFence < 0){
-          ALOGE("Failed to dup fence fd");
-        }
-      } else {
-        if (fenceHandle->numFds != 0) {
-          ALOGE("Invalid fence handle %p", fenceHandle);
-        }
-      }
-    }
-  });
-
-  return releaseFence;
-}
-
-}  // namespace android
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.h b/sensors/1.0/vts/functional/GrallocWrapper.h
deleted file mode 100644
index e506fe1..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRALLO_WRAPPER_H_
-#define GRALLO_WRAPPER_H_
-
-#include <unordered_set>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
-namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
-
-namespace android {
-
-// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
-class GrallocWrapper {
- public:
-  GrallocWrapper();
-  ~GrallocWrapper();
-
-  sp<allocator2::IAllocator> getAllocator() const;
-  sp<mapper2::IMapper> getMapper() const;
-
-  std::string dumpDebugInfo();
-
-  // When import is false, this simply calls IAllocator::allocate. When import
-  // is true, the returned buffers are also imported into the mapper.
-  //
-  // Either case, the returned buffers must be freed with freeBuffer.
-  std::vector<const native_handle_t*> allocate(
-      const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true,
-      uint32_t* outStride = nullptr);
-  const native_handle_t* allocate(
-      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
-      uint32_t* outStride = nullptr);
-
-  mapper2::BufferDescriptor createDescriptor(
-      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
-
-  const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
-  void freeBuffer(const native_handle_t* bufferHandle);
-
-  // We use fd instead of hardware::hidl_handle in these functions to pass fences
-  // in and out of the mapper.  The ownership of the fd is always transferred
-  // with each of these functions.
-  void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-             const mapper2::IMapper::Rect& accessRegion, int acquireFence);
-
-  int unlock(const native_handle_t* bufferHandle);
-
- private:
-  void init();
-  const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
-
-  sp<allocator2::IAllocator> mAllocator;
-  sp<mapper2::IMapper> mMapper;
-
-  // Keep track of all cloned and imported handles.  When a test fails with
-  // ASSERT_*, the destructor will free the handles for the test.
-  std::unordered_set<const native_handle_t*> mClonedBuffers;
-  std::unordered_set<const native_handle_t*> mImportedBuffers;
-};
-
-}  // namespace android
-#endif  // GRALLO_WRAPPER_H_
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
new file mode 100644
index 0000000..f8b021e
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsHidlEnvironmentV1_0.h"
+
+#include <log/log.h>
+
+#include <vector>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::sensors::V1_0::ISensors;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+
+bool SensorsHidlEnvironmentV1_0::resetHal() {
+    // wait upto 100ms * 10 = 1s for hidl service.
+    constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
+
+    std::string step;
+    bool succeed = false;
+    for (size_t retry = 10; retry > 0; --retry) {
+        // this do ... while is for easy error handling
+        do {
+            step = "getService()";
+            sensors = ISensors::getService(
+                SensorsHidlEnvironmentV1_0::Instance()->getServiceName<ISensors>());
+            if (sensors == nullptr) {
+                break;
+            }
+
+            step = "poll() check";
+            // Poke ISensor service. If it has lingering connection from previous generation of
+            // system server, it will kill itself. There is no intention to handle the poll result,
+            // which will be done since the size is 0.
+            if (!sensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
+                break;
+            }
+
+            step = "getSensorList";
+            std::vector<SensorInfo> sensorList;
+            if (!sensors
+                     ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
+                         sensorList.reserve(list.size());
+                         for (size_t i = 0; i < list.size(); ++i) {
+                             sensorList.push_back(list[i]);
+                         }
+                     })
+                     .isOk()) {
+                break;
+            }
+
+            // stop each sensor individually
+            step = "stop each sensor";
+            bool ok = true;
+            for (const auto& i : sensorList) {
+                if (!sensors->activate(i.sensorHandle, false).isOk()) {
+                    ok = false;
+                    break;
+                }
+            }
+            if (!ok) {
+                break;
+            }
+
+            // mark it done
+            step = "done";
+            succeed = true;
+        } while (0);
+
+        if (succeed) {
+            return true;
+        }
+
+        // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
+        ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
+        std::this_thread::sleep_for(RETRY_DELAY);
+    }
+
+    sensors = nullptr;
+    return false;
+}
+
+void SensorsHidlEnvironmentV1_0::startPollingThread() {
+    stopThread = false;
+    pollThread = std::thread(pollingThread, this, std::ref(stopThread));
+    events.reserve(128);
+}
+
+void SensorsHidlEnvironmentV1_0::pollingThread(SensorsHidlEnvironmentV1_0* env,
+                                               std::atomic_bool& stop) {
+    ALOGD("polling thread start");
+
+    while (!stop) {
+        env->sensors->poll(
+            64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+                if (result != Result::OK ||
+                    (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
+                    stop = true;
+                    return;
+                }
+
+                for (const auto& e : events) {
+                    env->addEvent(e);
+                }
+            });
+    }
+    ALOGD("polling thread end");
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
new file mode 100644
index 0000000..0a9e59f
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <utils/StrongPointer.h>
+
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+
+class SensorsHidlTest;
+class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    // get the test environment singleton
+    static SensorsHidlEnvironmentV1_0* Instance() {
+        static SensorsHidlEnvironmentV1_0* instance = new SensorsHidlEnvironmentV1_0();
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::sensors::V1_0::ISensors>();
+    }
+
+   private:
+    friend SensorsHidlTest;
+    // sensors hidl service
+    sp<android::hardware::sensors::V1_0::ISensors> sensors;
+
+    SensorsHidlEnvironmentV1_0() {}
+
+    bool resetHal() override;
+    void startPollingThread() override;
+    static void pollingThread(SensorsHidlEnvironmentV1_0* env, std::atomic_bool& stop);
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV1_0);
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index c18eedd..47308e1 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,583 +15,66 @@
  */
 
 #define LOG_TAG "sensors_hidl_hal_test"
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-#include <android-base/logging.h>
+
+#include "SensorsHidlEnvironmentV1_0.h"
+#include "sensors-vts-utils/SensorsHidlTestBase.h"
+
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
-#include <cutils/ashmem.h>
-#include <hardware/sensors.h>  // for sensor type strings
 #include <log/log.h>
 #include <utils/SystemClock.h>
-#include "GrallocWrapper.h"
 
-#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::GrallocWrapper;
 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 SensorsHidlTest;
-class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static SensorsHidlEnvironment* Instance() {
-        static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
-        return instance;
-    }
-
-    virtual void HidlSetUp() override;
-    virtual void HidlTearDown() override;
-
-    virtual void registerTestServices() override { registerTestService<ISensors>(); }
-
-    // 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:
-    friend SensorsHidlTest;
-    // sensors hidl service
-    sp<ISensors> sensors;
-
-    SensorsHidlEnvironment() {}
-
-    void addEvent(const Event& ev);
-    void startPollingThread();
-    void resetHal();
-    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::HidlSetUp() {
-    resetHal();
-
-    ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";
-
-    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::HidlTearDown() {
-    if (stopThread) {
-        *stopThread = true;
-    }
-    pollThread.detach();
-}
-
-void SensorsHidlEnvironment::resetHal() {
-  // wait upto 100ms * 10 = 1s for hidl service.
-  constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
-
-  std::string step;
-  bool succeed = false;
-  for (size_t retry = 10; retry > 0; --retry) {
-    // this do ... while is for easy error handling
-    do {
-      step = "getService()";
-      sensors = ISensors::getService(
-          SensorsHidlEnvironment::Instance()->getServiceName<ISensors>());
-      if (sensors == nullptr) {
-        break;
-      }
-
-      step = "poll() check";
-      // Poke ISensor service. If it has lingering connection from previous generation of
-      // system server, it will kill itself. There is no intention to handle the poll result,
-      // which will be done since the size is 0.
-      if(!sensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
-        break;
-      }
-
-      step = "getSensorList";
-      std::vector<SensorInfo> sensorList;
-      if (!sensors->getSensorsList(
-          [&] (const ::android::hardware::hidl_vec<SensorInfo> &list) {
-            sensorList.reserve(list.size());
-            for (size_t i = 0; i < list.size(); ++i) {
-              sensorList.push_back(list[i]);
-            }
-          }).isOk()) {
-        break;
-      }
-
-      // stop each sensor individually
-      step = "stop each sensor";
-      bool ok = true;
-      for (const auto &i : sensorList) {
-        if (!sensors->activate(i.sensorHandle, false).isOk()) {
-          ok = false;
-          break;
-        }
-      }
-      if (!ok) {
-        break;
-      }
-
-      // mark it done
-      step = "done";
-      succeed = true;
-    } while(0);
-
-    if (succeed) {
-      return;
-    }
-
-    // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
-    ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
-    std::this_thread::sleep_for(RETRY_DELAY);
-  }
-
-  sensors = nullptr;
-}
-
-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(64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
-          if (result != Result::OK
-              || (events.size() == 0 && dynamicSensorsAdded.size() == 0)
-              || *stop) {
-              needExit = true;
-              return;
-          }
-
-          for (const auto& e : events) {
-              env->addEvent(e);
-          }
-      });
-  }
-  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;
-  std::unique_ptr<GrallocWrapper> mGrallocWrapper;
-
-  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) {
-      ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, 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 %" PRId64 ", 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;
-    }
-    case SharedMemType::GRALLOC: {
-      mGrallocWrapper = std::make_unique<GrallocWrapper>();
-      if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) {
-        break;
-      }
-      using android::hardware::graphics::common::V1_0::BufferUsage;
-      using android::hardware::graphics::common::V1_0::PixelFormat;
-      mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
-        .width = static_cast<uint32_t>(size),
-        .height = 1,
-        .layerCount = 1,
-        .usage = static_cast<uint64_t> (BufferUsage::SENSOR_DIRECT_DATA |
-            BufferUsage::CPU_READ_OFTEN),
-        .format = PixelFormat::BLOB
-      };
-
-      handle = const_cast<native_handle_t *>(mGrallocWrapper->allocate(buf_desc_info));
-      if (handle != nullptr) {
-        mapper2::IMapper::Rect region{0, 0,
-            static_cast<int32_t>(buf_desc_info.width),
-            static_cast<int32_t>(buf_desc_info.height)};
-        buffer = static_cast<char *>
-                (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
-        if (buffer != nullptr) {
-          break;
-        }
-        mGrallocWrapper->freeBuffer(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;
-    }
-    case SharedMemType::GRALLOC: {
-      if (mSize != 0) {
-        mGrallocWrapper->unlock(mNativeHandle);
-        mGrallocWrapper->freeBuffer(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;
-}
-
-class SensorEventsChecker {
- public:
-  virtual bool check(const std::vector<Event> &events, std::string *out) const = 0;
-  virtual ~SensorEventsChecker() {}
-};
-
-class NullChecker : public SensorEventsChecker {
- public:
-  virtual bool check(const std::vector<Event> &, std::string *) const {
-    return true;
-  }
-};
-
-class SensorEventPerEventChecker : public SensorEventsChecker {
- public:
-  virtual bool checkEvent(const Event &event, std::string *out) const = 0;
-  virtual bool check(const std::vector<Event> &events, std::string *out) const {
-    for (const auto &e : events) {
-      if (!checkEvent(e, out)) {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-class Vec3NormChecker : public SensorEventPerEventChecker {
- public:
-  Vec3NormChecker(float min, float max) : mRange(min, max) {}
-  static Vec3NormChecker byNominal(float nominal, float allowedError) {
-    return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
-  }
-
-  virtual bool checkEvent(const Event &event, std::string *out) const {
-    Vec3 v = event.u.vec3;
-    float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
-    if (norm < mRange.first || norm > mRange.second) {
-      if (out != nullptr) {
-        std::ostringstream ss;
-        ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z << ")"
-           << " has norm " << norm << ", which is beyond range"
-           << " [" << mRange.first << ", " << mRange.second << "]";
-        *out = ss.str();
-      }
-      return false;
-    }
-    return true;
-  }
- protected:
-  std::pair<float, float> mRange;
-};
-
 // The main test class for SENSORS HIDL HAL.
-class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
-  virtual void SetUp() override {
-  }
 
-  virtual void TearDown() override {
-    // stop all sensors
-    for (auto s : mSensorHandles) {
-      S()->activate(s, false);
+class SensorsHidlTest : public SensorsHidlTestBase {
+   protected:
+    SensorInfo defaultSensorByType(SensorType type) override;
+    std::vector<SensorInfo> getSensorsList();
+    // implementation wrapper
+    Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
+        return S()->getSensorsList(_hidl_cb);
     }
-    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);
+    Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                         int64_t maxReportLatencyNs) override {
+        return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
     }
-    mDirectChannelHandles.clear();
-  }
 
- protected:
-  SensorInfo defaultSensorByType(SensorType type);
-  std::vector<SensorInfo> getSensorsList();
-  std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
-        bool clearBeforeStart = true, bool changeCollection = true);
+    Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); }
 
-  // implementation wrapper
-  Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) {
-    return S()->getSensorsList(_hidl_cb);
-  }
+    Return<Result> injectSensorData(const Event& event) override {
+        return S()->injectSensorData(event);
+    }
 
-  Return<Result> activate(
-          int32_t sensorHandle, bool enabled);
+    Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                       ISensors::registerDirectChannel_cb _hidl_cb) override;
 
-  Return<Result> batch(
-          int32_t sensorHandle,
-          int64_t samplingPeriodNs,
-          int64_t maxReportLatencyNs) {
-    return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
-  }
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+        return S()->unregisterDirectChannel(channelHandle);
+    }
 
-  Return<Result> flush(int32_t sensorHandle) {
-    return S()->flush(sensorHandle);
-  }
+    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+                                    ISensors::configDirectReport_cb _hidl_cb) override {
+        return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+    }
 
-  Return<Result> injectSensorData(const Event& event) {
-    return S()->injectSensorData(event);
-  }
+    inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }
 
-  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;
-  }
-
-  void testStreamingOperation(SensorType type,
-                              std::chrono::nanoseconds samplingPeriod,
-                              std::chrono::seconds duration,
-                              const SensorEventsChecker &checker);
-  void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
-  void testBatchingOperation(SensorType type);
-  void testDirectReportOperation(
-      SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker);
-
-  static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
-  static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
-  static void assertDelayMatchReportMode(
-          int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode);
-  static SensorFlagBits expectedReportModeForType(SensorType type);
-  static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
-  static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
-
-  // checkers
-  static const Vec3NormChecker sAccelNormChecker;
-  static const Vec3NormChecker sGyroNormChecker;
-
-  // all sensors and direct channnels used
-  std::unordered_set<int32_t> mSensorHandles;
-  std::unordered_set<int32_t> mDirectChannelHandles;
+    SensorsHidlEnvironmentBase* getEnvironment() override {
+        return SensorsHidlEnvironmentV1_0::Instance();
+    }
 };
 
-const Vec3NormChecker SensorsHidlTest::sAccelNormChecker(
-        Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f/*m/s^2*/));
-const Vec3NormChecker SensorsHidlTest::sGyroNormChecker(
-        Vec3NormChecker::byNominal(0.f, 0.1f/*rad/s*/));
-
 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
@@ -618,195 +101,6 @@
   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; //granularity 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;
-}
-
-void SensorsHidlTest::assertTypeMatchStringType(SensorType type, const hidl_string& stringType) {
-
-  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
-    return;
-  }
-
-  switch (type) {
-#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
-    case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType.c_str()); break;
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
-    default:
-      FAIL() << "Type " << static_cast<int>(type) << " in android defined range is not checked, "
-             << "stringType = " << stringType;
-#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
-  }
-}
-
-void SensorsHidlTest::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
-  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
-    return;
-  }
-
-  SensorFlagBits expected = expectedReportModeForType(type);
-
-  ASSERT_TRUE(expected == (SensorFlagBits) -1 || expected == reportMode)
-      << "reportMode=" << static_cast<int>(reportMode)
-      << "expected=" << static_cast<int>(expected);
-}
-
-void SensorsHidlTest::assertDelayMatchReportMode(
-    int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode) {
-  switch(reportMode) {
-    case SensorFlagBits::CONTINUOUS_MODE:
-      ASSERT_LT(0, minDelay);
-      ASSERT_LE(0, maxDelay);
-      break;
-    case SensorFlagBits::ON_CHANGE_MODE:
-      ASSERT_LE(0, minDelay);
-      ASSERT_LE(0, maxDelay);
-      break;
-    case SensorFlagBits::ONE_SHOT_MODE:
-      ASSERT_EQ(-1, minDelay);
-      ASSERT_EQ(0, maxDelay);
-      break;
-    case SensorFlagBits::SPECIAL_REPORTING_MODE:
-      // do not enforce anything for special reporting mode
-      break;
-    default:
-      FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
-  }
-}
-
-// return -1 means no expectation for this type
-SensorFlagBits SensorsHidlTest::expectedReportModeForType(SensorType type) {
-  switch (type) {
-    case SensorType::ACCELEROMETER:
-    case SensorType::ACCELEROMETER_UNCALIBRATED:
-    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::STEP_COUNTER:
-    case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-      return SensorFlagBits::ON_CHANGE_MODE;
-
-    case SensorType::SIGNIFICANT_MOTION:
-    case SensorType::WAKE_GESTURE:
-    case SensorType::GLANCE_GESTURE:
-    case SensorType::PICK_UP_GESTURE:
-    case SensorType::MOTION_DETECT:
-    case SensorType::STATIONARY_DETECT:
-      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;
-  }
-}
-
-bool SensorsHidlTest::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
-  unsigned int r =
-      static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT)
-        >> static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
-  return r >= static_cast<unsigned int>(rate);
-}
-
-bool SensorsHidlTest::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
-  switch (type) {
-    case SharedMemType::ASHMEM:
-      return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
-    case SharedMemType::GRALLOC:
-      return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
-    default:
-      return false;
-  }
-}
-
 SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
   SensorInfo ret;
 
@@ -951,69 +245,6 @@
     ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
 }
 
-void SensorsHidlTest::testStreamingOperation(SensorType type,
-                                             std::chrono::nanoseconds samplingPeriod,
-                                             std::chrono::seconds duration,
-                                             const SensorEventsChecker &checker) {
-  std::vector<Event> events;
-  std::vector<Event> sensorEvents;
-
-  const int64_t samplingPeriodInNs = samplingPeriod.count();
-  const int64_t batchingPeriodInNs = 0; // no batching
-  const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
-  const size_t minNEvent = duration / samplingPeriod;
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
-    // rate not supported
-    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);
-
-  bool handleMismatchReported = false;
-  bool metaSensorTypeErrorReported = false;
-  for (auto & e : events) {
-    if (e.sensorType == type) {
-      // avoid generating hundreds of error
-      if (!handleMismatchReported) {
-        EXPECT_EQ(e.sensorHandle, handle)
-            << (handleMismatchReported = true,
-                "Event of the same type must come from the sensor registered");
-      }
-      sensorEvents.push_back(e);
-    } else {
-      // avoid generating hundreds of error
-      if (!metaSensorTypeErrorReported) {
-        EXPECT_TRUE(isMetaSensorType(e.sensorType))
-            << (metaSensorTypeErrorReported = true,
-                "Only meta types are allowed besides the type registered");
-      }
-    }
-  }
-
-  std::string s;
-  EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
-  EXPECT_GE(sensorEvents.size(),
-            minNEvent / 2);  // make sure returned events are not all meta
-}
-
 // Test if sensor hal can do UI speed accelerometer streaming properly
 TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
   testStreamingOperation(SensorType::ACCELEROMETER,
@@ -1086,103 +317,6 @@
                          NullChecker());
 }
 
-void SensorsHidlTest::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
-  std::vector<Event> events1, events2;
-
-  constexpr int64_t batchingPeriodInNs = 0; // no batching
-  constexpr int64_t collectionTimeoutUs = 60000000; // 60s
-  constexpr size_t minNEvent = 50;
-
-  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;
-  }
-
-  int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
-  int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
-
-  // first collection
-  ASSERT_EQ(batch(handle, firstCollectionPeriod, 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(collectionTimeoutUs, minNEvent);
-
-  // second collection, without stop sensor
-  ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
-
-  usleep(500000); // sleep 0.5 sec to wait for change rate to happen
-  events2 = collectEvents(collectionTimeoutUs, minNEvent);
-
-  // end of collection, stop sensor
-  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;
-  std::vector<Event> &minDelayEvents(fastToSlow ? events1 : events2);
-  std::vector<Event> &maxDelayEvents(fastToSlow ? events2 : events1);
-
-  size_t nEvent = 0;
-  int64_t prevTimestamp = -1;
-  int64_t timestampInterval = 0;
-  for (auto & e : minDelayEvents) {
-    if (e.sensorType == type) {
-      ASSERT_EQ(e.sensorHandle, handle);
-      if (prevTimestamp > 0) {
-        timestampInterval += e.timestamp - prevTimestamp;
-      }
-      prevTimestamp = e.timestamp;
-      ++ nEvent;
-    }
-  }
-  ASSERT_GT(nEvent, 2u);
-  minDelayAverageInterval = timestampInterval / (nEvent - 1);
-
-  nEvent = 0;
-  prevTimestamp = -1;
-  timestampInterval = 0;
-  for (auto & e : maxDelayEvents) {
-    if (e.sensorType == type) {
-      ASSERT_EQ(e.sensorHandle, handle);
-      if (prevTimestamp > 0) {
-        timestampInterval += e.timestamp - prevTimestamp;
-      }
-      prevTimestamp = e.timestamp;
-      ++ nEvent;
-    }
-  }
-  ASSERT_GT(nEvent, 2u);
-  maxDelayAverageInterval = timestampInterval / (nEvent - 1);
-
-  // change of rate is significant.
-  ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64,
-      minDelayAverageInterval, maxDelayAverageInterval);
-  EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
-
-  // fastest rate sampling time is close to spec
-  EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
-      minSamplingPeriodInNs / 10);
-
-  // slowest rate sampling time is close to spec
-  EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
-      maxSamplingPeriodInNs / 10);
-}
-
 // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
 TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
   testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
@@ -1201,74 +335,6 @@
   testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
 }
 
-void SensorsHidlTest::testBatchingOperation(SensorType type) {
-  std::vector<Event> events;
-
-  constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
-  constexpr int64_t oneSecondInNs = 1ull * 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);
-  // clean existing collections
-  collectEvents(0 /*timeLimitUs*/, 0/*nEventLimit*/,
-        true /*clearBeforeStart*/, false /*change collection*/);
-
-  // 0.8 + 0.2 times the batching period
-  usleep(batchingPeriodInNs / 1000 * 8 / 10);
-  ASSERT_EQ(flush(handle), Result::OK);
-
-  // plus some time for the event to deliver
-  events = collectEvents(allowedBatchDeliverTimeNs / 1000,
-        minFifoCount, false /*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)(minFifoCount * 9 / 10));
-}
-
 // Test if sensor hal can do accelerometer batching properly
 TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
   testBatchingOperation(SensorType::ACCELEROMETER);
@@ -1284,124 +350,6 @@
   testBatchingOperation(SensorType::MAGNETIC_FIELD);
 }
 
-void SensorsHidlTest::testDirectReportOperation(
-    SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
-  constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
-  constexpr size_t kNEvent = 4096;
-  constexpr size_t kMemSize = kEventSize * kNEvent;
-
-  constexpr float kNormalNominal = 50;
-  constexpr float kFastNominal = 200;
-  constexpr float kVeryFastNominal = 800;
-
-  constexpr float kNominalTestTimeSec = 1.f;
-  constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  if (!isDirectReportRateSupported(sensor, rate)) {
-    return;
-  }
-
-  if (!isDirectChannelTypeSupported(sensor, memType)) {
-    return;
-  }
-
-  std::unique_ptr<SensorsTestSharedMemory>
-      mem(SensorsTestSharedMemory::create(memType, 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, rate,
-      [&eventToken] (auto result, auto token) {
-          ASSERT_EQ(result, Result::OK);
-          eventToken = token;
-      });
-
-  usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
-  auto events = mem->parseEvents();
-
-  // find norminal rate
-  float nominalFreq = 0.f;
-  switch (rate) {
-      case RateLevel::NORMAL:
-          nominalFreq = kNormalNominal;
-          break;
-      case RateLevel::FAST:
-          nominalFreq = kFastNominal;
-          break;
-      case RateLevel::VERY_FAST:
-          nominalFreq = kVeryFastNominal;
-          break;
-      case RateLevel::STOP:
-          FAIL();
-  }
-
-  // allowed to be between 55% and 220% of nominal freq
-  ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
-  ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
-
-  int64_t lastTimestamp = 0;
-  bool typeErrorReported = false;
-  bool tokenErrorReported = false;
-  bool timestampErrorReported = false;
-  std::vector<Event> sensorEvents;
-  for (auto &e : events) {
-    if (!tokenErrorReported) {
-      EXPECT_EQ(eventToken, e.sensorHandle)
-          << (tokenErrorReported = true,
-            "Event token does not match that retured from configDirectReport");
-    }
-
-    if (isMetaSensorType(e.sensorType)) {
-        continue;
-    }
-    sensorEvents.push_back(e);
-
-    if (!typeErrorReported) {
-      EXPECT_EQ(type, e.sensorType)
-          << (typeErrorReported = true,
-              "Type in event does not match type of sensor registered.");
-    }
-    if (!timestampErrorReported) {
-      EXPECT_GT(e.timestamp, lastTimestamp)
-          << (timestampErrorReported = true, "Timestamp not monotonically increasing");
-    }
-    lastTimestamp = e.timestamp;
-  }
-
-  std::string s;
-  EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
-  // stop sensor and unregister channel
-  configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
-                     [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
-  EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
-}
-
 // Test sensor event direct report with ashmem for accel sensor at normal rate
 TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
   testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
@@ -1511,11 +459,11 @@
 }
 
 int main(int argc, char **argv) {
-  ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  SensorsHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
+    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
 // vim: set ts=2 sw=2
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..8e8413c
--- /dev/null
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -0,0 +1,33 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalSensorsV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "SensorsHidlEnvironmentV2_0.cpp",
+        "VtsHalSensorsV2_0TargetTest.cpp"
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.sensors@1.0",
+        "android.hardware.sensors@2.0",
+        "libfmq",
+        "VtsHalSensorsTargetTestUtils",
+    ],
+}
+
diff --git a/sensors/2.0/vts/functional/OWNERS b/sensors/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/2.0/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
new file mode 100644
index 0000000..5444287
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsHidlEnvironmentV2_0.h"
+
+#include <android/hardware/sensors/2.0/types.h>
+#include <log/log.h>
+
+#include <algorithm>
+#include <vector>
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V2_0::EventQueueFlagBits;
+using ::android::hardware::sensors::V2_0::ISensors;
+
+template <typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+    return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
+
+bool SensorsHidlEnvironmentV2_0::resetHal() {
+    bool succeed = false;
+    do {
+        mSensors = ISensors::getService(
+            SensorsHidlEnvironmentV2_0::Instance()->getServiceName<ISensors>());
+        if (mSensors == nullptr) {
+            break;
+        }
+
+        // Initialize FMQs
+        mEventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+                                                          true /* configureEventFlagWord */);
+
+        mWakeLockQueue = std::make_unique<WakeLockQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+                                                         true /* configureEventFlagWord */);
+
+        if (mEventQueue == nullptr || mWakeLockQueue == nullptr) {
+            break;
+        }
+
+        EventFlag::deleteEventFlag(&mEventQueueFlag);
+        EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
+        if (mEventQueueFlag == nullptr) {
+            break;
+        }
+
+        mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(),
+                             nullptr /* TODO: callback */);
+
+        std::vector<SensorInfo> sensorList;
+        if (!mSensors->getSensorsList([&](const hidl_vec<SensorInfo>& list) { sensorList = list; })
+                 .isOk()) {
+            break;
+        }
+
+        // stop each sensor individually
+        bool ok = true;
+        for (const auto& i : sensorList) {
+            if (!mSensors->activate(i.sensorHandle, false).isOk()) {
+                ok = false;
+                break;
+            }
+        }
+        if (!ok) {
+            break;
+        }
+
+        // mark it done
+        succeed = true;
+    } while (0);
+
+    if (!succeed) {
+        mSensors = nullptr;
+    }
+
+    return succeed;
+}
+
+void SensorsHidlEnvironmentV2_0::HidlTearDown() {
+    stopThread = true;
+
+    // Wake up the event queue so the poll thread can exit
+    mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS));
+    pollThread.join();
+
+    EventFlag::deleteEventFlag(&mEventQueueFlag);
+}
+
+void SensorsHidlEnvironmentV2_0::startPollingThread() {
+    stopThread = false;
+    pollThread = std::thread(pollingThread, this);
+    events.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
+}
+
+void SensorsHidlEnvironmentV2_0::readEvents() {
+    size_t availableEvents = mEventQueue->availableToRead();
+
+    if (availableEvents == 0) {
+        uint32_t eventFlagState = 0;
+
+        mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS), &eventFlagState);
+        availableEvents = mEventQueue->availableToRead();
+    }
+
+    size_t eventsToRead = std::min(availableEvents, mEventBuffer.size());
+    if (eventsToRead > 0) {
+        if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
+            for (const auto& e : mEventBuffer) {
+                addEvent(e);
+            }
+        }
+    }
+}
+
+void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* env) {
+    ALOGD("polling thread start");
+
+    while (!env->stopThread.load()) {
+        env->readEvents();
+    }
+
+    ALOGD("polling thread end");
+}
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
new file mode 100644
index 0000000..7241923
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
+
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <android/hardware/sensors/1.0/types.h>
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <fmq/MessageQueue.h>
+#include <utils/StrongPointer.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+using ::android::hardware::MessageQueue;
+
+class SensorsHidlTest;
+class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    // get the test environment singleton
+    static SensorsHidlEnvironmentV2_0* Instance() {
+        static SensorsHidlEnvironmentV2_0* instance = new SensorsHidlEnvironmentV2_0();
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::sensors::V2_0::ISensors>();
+    }
+
+    virtual void HidlTearDown() override;
+
+   private:
+    friend SensorsHidlTest;
+
+    SensorsHidlEnvironmentV2_0() : mEventQueueFlag(nullptr) {}
+
+    /**
+     * Resets the HAL with new FMQs and a new Event Flag
+     *
+     * @return bool true if successful, false otherwise
+     */
+    bool resetHal() override;
+
+    /**
+     * Starts the polling thread that reads sensor events from the Event FMQ
+     */
+    void startPollingThread() override;
+
+    /**
+     * Thread responsible for calling functions to read Event FMQ
+     *
+     * @param env SensorEnvironment to being polling for events on
+     */
+    static void pollingThread(SensorsHidlEnvironmentV2_0* env);
+
+    /**
+     * Reads and saves sensor events from the Event FMQ
+     */
+    void readEvents();
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0);
+
+    /**
+     * Pointer to the Sensors HAL Interface that allows the test to call HAL functions.
+     */
+    sp<android::hardware::sensors::V2_0::ISensors> mSensors;
+
+    /**
+     * Type used to simplify the creation of the Event FMQ
+     */
+    typedef MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite> EventMessageQueue;
+
+    /**
+     * Type used to simplify the creation of the Wake Lock FMQ
+     */
+    typedef MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite> WakeLockQueue;
+
+    /**
+     * The Event FMQ where the test framework is able to read sensor events that the Sensors HAL
+     * has written.
+     */
+    std::unique_ptr<EventMessageQueue> mEventQueue;
+
+    /**
+     * The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed
+     * WAKE_UP sensor events.
+     */
+    std::unique_ptr<WakeLockQueue> mWakeLockQueue;
+
+    /**
+     * The Event Queue Flag notifies the test framework when sensor events have been written to the
+     * Event FMQ by the Sensors HAL.
+     */
+    ::android::hardware::EventFlag* mEventQueueFlag;
+
+    /**
+     * The maximum number of sensor events that can be read from the Event FMQ at one time.
+     */
+    static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 128;
+
+    /**
+     * An array that is used to store sensor events read from the Event FMQ
+     */
+    std::array<Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
new file mode 100644
index 0000000..7c6f010
--- /dev/null
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "sensors_hidl_hal_test"
+
+#include "SensorsHidlEnvironmentV2_0.h"
+#include "sensors-vts-utils/SensorsHidlTestBase.h"
+
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <android/hardware/sensors/2.0/types.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <cinttypes>
+#include <vector>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V1_0::Vec3;
+
+// The main test class for SENSORS HIDL HAL.
+
+class SensorsHidlTest : public SensorsHidlTestBase {
+   protected:
+    SensorInfo defaultSensorByType(SensorType type) override;
+    std::vector<SensorInfo> getSensorsList();
+    // implementation wrapper
+    Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
+        return getSensors()->getSensorsList(_hidl_cb);
+    }
+
+    Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                         int64_t maxReportLatencyNs) override {
+        return getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+    }
+
+    Return<Result> flush(int32_t sensorHandle) override {
+        return getSensors()->flush(sensorHandle);
+    }
+
+    Return<Result> injectSensorData(const Event& event) override {
+        return getSensors()->injectSensorData(event);
+    }
+
+    Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                       ISensors::registerDirectChannel_cb _hidl_cb) override;
+
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+        return getSensors()->unregisterDirectChannel(channelHandle);
+    }
+
+    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+                                    ISensors::configDirectReport_cb _hidl_cb) override {
+        return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+    }
+
+    inline sp<::android::hardware::sensors::V2_0::ISensors>& getSensors() {
+        return SensorsHidlEnvironmentV2_0::Instance()->mSensors;
+    }
+
+    SensorsHidlEnvironmentBase* getEnvironment() override {
+        return SensorsHidlEnvironmentV2_0::Instance();
+    }
+};
+
+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 getSensors()->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.
+    getSensors()->registerDirectChannel(mem, [&](auto result, auto channelHandle) {
+        if (result == Result::OK) {
+            mDirectChannelHandles.insert(channelHandle);
+        }
+        cb(result, channelHandle);
+    });
+    return Void();
+}
+
+SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
+    SensorInfo ret;
+
+    ret.type = (SensorType)-1;
+    getSensors()->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;
+}
+
+std::vector<SensorInfo> SensorsHidlTest::getSensorsList() {
+    std::vector<SensorInfo> ret;
+
+    getSensors()->getSensorsList([&](const auto& list) {
+        const size_t count = list.size();
+        ret.reserve(list.size());
+        for (size_t i = 0; i < count; ++i) {
+            ret.push_back(list[i]);
+        }
+    });
+
+    return ret;
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, SensorListValid) {
+    getSensors()->getSensorsList([&](const auto& list) {
+        const size_t count = list.size();
+        for (size_t i = 0; i < count; ++i) {
+            const auto& s = list[i];
+            SCOPED_TRACE(::testing::Message()
+                         << i << "/" << count << ": "
+                         << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                         << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+                         << " name=" << s.name);
+
+            // Test non-empty type string
+            EXPECT_FALSE(s.typeAsString.empty());
+
+            // Test defined type matches defined string type
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString));
+
+            // Test if all sensor has name and vendor
+            EXPECT_FALSE(s.name.empty());
+            EXPECT_FALSE(s.vendor.empty());
+
+            // Test power > 0, maxRange > 0
+            EXPECT_LE(0, s.power);
+            EXPECT_LT(0, s.maxRange);
+
+            // Info type, should have no sensor
+            EXPECT_FALSE(s.type == SensorType::ADDITIONAL_INFO || s.type == SensorType::META_DATA);
+
+            // Test fifoMax >= fifoReserved
+            EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount)
+                << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount;
+
+            // Test Reporting mode valid
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags)));
+
+            // Test min max are in the right order
+            EXPECT_LE(s.minDelay, s.maxDelay);
+            // Test min/max delay matches reporting mode
+            EXPECT_NO_FATAL_FAILURE(
+                assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
+        }
+    });
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, SetOperationMode) {
+    std::vector<SensorInfo> sensorList = getSensorsList();
+
+    bool needOperationModeSupport =
+        std::any_of(sensorList.begin(), sensorList.end(),
+                    [](const auto& s) { return (s.flags & SensorFlagBits::DATA_INJECTION) != 0; });
+    if (!needOperationModeSupport) {
+        return;
+    }
+
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, InjectSensorEventData) {
+    std::vector<SensorInfo> sensorList = getSensorsList();
+    std::vector<SensorInfo> sensorSupportInjection;
+
+    bool needOperationModeSupport =
+        std::any_of(sensorList.begin(), sensorList.end(), [&sensorSupportInjection](const auto& s) {
+            bool ret = (s.flags & SensorFlagBits::DATA_INJECTION) != 0;
+            if (ret) {
+                sensorSupportInjection.push_back(s);
+            }
+            return ret;
+        });
+    if (!needOperationModeSupport) {
+        return;
+    }
+
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
+
+    for (const auto& s : sensorSupportInjection) {
+        switch (s.type) {
+            case SensorType::ACCELEROMETER:
+            case SensorType::GYROSCOPE:
+            case SensorType::MAGNETIC_FIELD: {
+                usleep(100000);  // sleep 100ms
+
+                Event dummy;
+                dummy.timestamp = android::elapsedRealtimeNano();
+                dummy.sensorType = s.type;
+                dummy.sensorHandle = s.sensorHandle;
+                Vec3 v = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
+                dummy.u.vec3 = v;
+
+                EXPECT_EQ(Result::OK, getSensors()->injectSensorData(dummy));
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::NORMAL));
+}
+
+// Test if sensor hal can do UI speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do normal speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do game speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do UI speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do normal speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do game speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do UI speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do normal speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do game speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do accelerometer batching properly
+TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
+    testBatchingOperation(SensorType::ACCELEROMETER);
+}
+
+// Test if sensor hal can do gyroscope batching properly
+TEST_F(SensorsHidlTest, GyroscopeBatchingOperation) {
+    testBatchingOperation(SensorType::GYROSCOPE);
+}
+
+// Test if sensor hal can do magnetometer batching properly
+TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
+    testBatchingOperation(SensorType::MAGNETIC_FIELD);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at normal rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at fast rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at very fast rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at normal rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at fast rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at very fast rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for mag sensor at normal rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              NullChecker());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at fast rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
+                              NullChecker());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at very fast rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, NullChecker());
+}
+
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
+                              NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, NullChecker());
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SensorsHidlEnvironmentV2_0::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
+// vim: set ts=2 sw=2
diff --git a/sensors/common/vts/OWNERS b/sensors/common/vts/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
new file mode 100644
index 0000000..95df425
--- /dev/null
+++ b/sensors/common/vts/utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "VtsHalSensorsTargetTestUtils",
+    srcs: [
+        "GrallocWrapper.cpp",
+        "SensorsHidlEnvironmentBase.cpp",
+        "SensorsHidlTestBase.cpp",
+        "SensorsTestSharedMemory.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    local_include_dirs: [
+        "include/sensors-vts-utils",
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.sensors@1.0",
+        "VtsHalHidlTargetTestBase",
+    ],
+}
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
new file mode 100644
index 0000000..7bed16d
--- /dev/null
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -0,0 +1,224 @@
+/*
+ * 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 "GrallocWrapper"
+
+#include "GrallocWrapper.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+GrallocWrapper::GrallocWrapper() {
+    init();
+}
+
+void GrallocWrapper::init() {
+    mAllocator = allocator2::IAllocator::getService();
+    if (mAllocator == nullptr) {
+        ALOGE("Failed to get allocator service");
+    }
+
+    mMapper = mapper2::IMapper::getService();
+    if (mMapper == nullptr) {
+        ALOGE("Failed to get mapper service");
+    }
+    if (mMapper->isRemote()) {
+        ALOGE("Mapper is not in passthrough mode");
+    }
+}
+
+GrallocWrapper::~GrallocWrapper() {
+    for (auto bufferHandle : mClonedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+    mClonedBuffers.clear();
+
+    for (auto bufferHandle : mImportedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
+            ALOGE("Failed to free buffer %p", buffer);
+        }
+    }
+    mImportedBuffers.clear();
+}
+
+sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
+    return mAllocator;
+}
+
+std::string GrallocWrapper::dumpDebugInfo() {
+    std::string debugInfo;
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+
+    if (bufferHandle) {
+        mClonedBuffers.insert(bufferHandle);
+    }
+    return bufferHandle;
+}
+
+std::vector<const native_handle_t*> GrallocWrapper::allocate(
+    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
+    std::vector<const native_handle_t*> bufferHandles;
+    bufferHandles.reserve(count);
+    mAllocator->allocate(descriptor, count,
+                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+                             if (mapper2::Error::NONE != tmpError) {
+                                 ALOGE("Failed to allocate buffers");
+                             }
+                             if (count != tmpBuffers.size()) {
+                                 ALOGE("Invalid buffer array");
+                             }
+
+                             for (uint32_t i = 0; i < count; i++) {
+                                 if (import) {
+                                     bufferHandles.push_back(importBuffer(tmpBuffers[i]));
+                                 } else {
+                                     bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
+                                 }
+                             }
+
+                             if (outStride) {
+                                 *outStride = tmpStride;
+                             }
+                         });
+
+    return bufferHandles;
+}
+
+const native_handle_t* GrallocWrapper::allocate(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+    uint32_t* outStride) {
+    mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    auto buffers = allocate(descriptor, 1, import, outStride);
+    return buffers[0];
+}
+
+sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
+    return mMapper;
+}
+
+mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
+    mapper2::BufferDescriptor descriptor;
+    mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to create descriptor");
+        }
+        descriptor = tmpDescriptor;
+    });
+
+    return descriptor;
+}
+
+const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
+        }
+        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+    });
+
+    if (bufferHandle) {
+        mImportedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
+}
+
+void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    if (mImportedBuffers.erase(bufferHandle)) {
+        mapper2::Error error = mMapper->freeBuffer(buffer);
+        if (error != mapper2::Error::NONE) {
+            ALOGE("Failed to free %p", buffer);
+        }
+    } else {
+        mClonedBuffers.erase(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+}
+
+void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                           const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hardware::hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    void* data = nullptr;
+    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                  [&](const auto& tmpError, const auto& tmpData) {
+                      if (tmpError != mapper2::Error::NONE) {
+                          ALOGE("Failed to lock buffer %p", buffer);
+                      }
+                      data = tmpData;
+                  });
+
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return data;
+}
+
+int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to unlock buffer %p", buffer);
+        }
+
+        auto fenceHandle = tmpReleaseFence.getNativeHandle();
+        if (fenceHandle) {
+            if (fenceHandle->numInts != 0) {
+                ALOGE("Invalid fence handle %p", fenceHandle);
+            }
+            if (fenceHandle->numFds == 1) {
+                releaseFence = dup(fenceHandle->data[0]);
+                if (releaseFence < 0) {
+                    ALOGE("Failed to dup fence fd");
+                }
+            } else {
+                if (fenceHandle->numFds != 0) {
+                    ALOGE("Invalid fence handle %p", fenceHandle);
+                }
+            }
+        }
+    });
+
+    return releaseFence;
+}
+
+}  // namespace android
diff --git a/sensors/common/vts/utils/OWNERS b/sensors/common/vts/utils/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/utils/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
new file mode 100644
index 0000000..21c08d2
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsHidlEnvironmentBase.h"
+
+void SensorsHidlEnvironmentBase::HidlSetUp() {
+    ASSERT_TRUE(resetHal()) << "could not get hidl service";
+
+    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 SensorsHidlEnvironmentBase::HidlTearDown() {
+    stopThread = true;
+    pollThread.detach();
+}
+
+void SensorsHidlEnvironmentBase::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 SensorsHidlEnvironmentBase::setCollection(bool enable) {
+    std::lock_guard<std::mutex> lock(events_mutex);
+    collectionEnabled = enable;
+}
+
+void SensorsHidlEnvironmentBase::addEvent(const Event& ev) {
+    std::lock_guard<std::mutex> lock(events_mutex);
+    if (collectionEnabled) {
+        events.push_back(ev);
+    }
+}
diff --git a/sensors/common/vts/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
new file mode 100644
index 0000000..b72fdfd
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsHidlTestBase.h"
+
+#include "sensors-vts-utils/GrallocWrapper.h"
+#include "sensors-vts-utils/SensorsTestSharedMemory.h"
+
+#include <hardware/sensors.h>  // for sensor type strings
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <cinttypes>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::sensors::V1_0::SensorFlagShift;
+using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
+
+const Vec3NormChecker SensorsHidlTestBase::sAccelNormChecker(
+    Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/));
+const Vec3NormChecker SensorsHidlTestBase::sGyroNormChecker(
+    Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/));
+
+std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+                                                      bool clearBeforeStart,
+                                                      bool changeCollection) {
+    std::vector<Event> events;
+    constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000;  // granularity 100 ms
+
+    ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
+          clearBeforeStart);
+
+    if (changeCollection) {
+        getEnvironment()->setCollection(true);
+    }
+    if (clearBeforeStart) {
+        getEnvironment()->catEvents(nullptr);
+    }
+
+    while (timeLimitUs > 0) {
+        useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
+        usleep(duration);
+        timeLimitUs -= duration;
+
+        getEnvironment()->catEvents(&events);
+        if (events.size() >= nEventLimit) {
+            break;
+        }
+        ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
+              (int)(nEventLimit - events.size()));
+    }
+
+    if (changeCollection) {
+        getEnvironment()->setCollection(false);
+    }
+    return events;
+}
+
+void SensorsHidlTestBase::assertTypeMatchStringType(SensorType type,
+                                                    const hidl_string& stringType) {
+    if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+        return;
+    }
+
+    switch (type) {
+#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type)                      \
+    case SensorType::type:                                           \
+        ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
+        break;
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
+        default:
+            FAIL() << "Type " << static_cast<int>(type)
+                   << " in android defined range is not checked, "
+                   << "stringType = " << stringType;
+#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
+    }
+}
+
+void SensorsHidlTestBase::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
+    if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+        return;
+    }
+
+    SensorFlagBits expected = expectedReportModeForType(type);
+
+    ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode)
+        << "reportMode=" << static_cast<int>(reportMode)
+        << "expected=" << static_cast<int>(expected);
+}
+
+void SensorsHidlTestBase::assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+                                                     SensorFlagBits reportMode) {
+    switch (reportMode) {
+        case SensorFlagBits::CONTINUOUS_MODE:
+            ASSERT_LT(0, minDelay);
+            ASSERT_LE(0, maxDelay);
+            break;
+        case SensorFlagBits::ON_CHANGE_MODE:
+            ASSERT_LE(0, minDelay);
+            ASSERT_LE(0, maxDelay);
+            break;
+        case SensorFlagBits::ONE_SHOT_MODE:
+            ASSERT_EQ(-1, minDelay);
+            ASSERT_EQ(0, maxDelay);
+            break;
+        case SensorFlagBits::SPECIAL_REPORTING_MODE:
+            // do not enforce anything for special reporting mode
+            break;
+        default:
+            FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
+    }
+}
+
+// return -1 means no expectation for this type
+SensorFlagBits SensorsHidlTestBase::expectedReportModeForType(SensorType type) {
+    switch (type) {
+        case SensorType::ACCELEROMETER:
+        case SensorType::ACCELEROMETER_UNCALIBRATED:
+        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::STEP_COUNTER:
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT:
+            return SensorFlagBits::ON_CHANGE_MODE;
+
+        case SensorType::SIGNIFICANT_MOTION:
+        case SensorType::WAKE_GESTURE:
+        case SensorType::GLANCE_GESTURE:
+        case SensorType::PICK_UP_GESTURE:
+        case SensorType::MOTION_DETECT:
+        case SensorType::STATIONARY_DETECT:
+            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;
+    }
+}
+
+bool SensorsHidlTestBase::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
+    unsigned int r = static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
+                     static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
+    return r >= static_cast<unsigned int>(rate);
+}
+
+bool SensorsHidlTestBase::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
+    switch (type) {
+        case SharedMemType::ASHMEM:
+            return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
+        case SharedMemType::GRALLOC:
+            return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
+        default:
+            return false;
+    }
+}
+
+void SensorsHidlTestBase::testDirectReportOperation(SensorType type, SharedMemType memType,
+                                                    RateLevel rate,
+                                                    const SensorEventsChecker& checker) {
+    constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+    constexpr size_t kNEvent = 4096;
+    constexpr size_t kMemSize = kEventSize * kNEvent;
+
+    constexpr float kNormalNominal = 50;
+    constexpr float kFastNominal = 200;
+    constexpr float kVeryFastNominal = 800;
+
+    constexpr float kNominalTestTimeSec = 1.f;
+    constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f;  // 0.5 second for initialization
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    if (!isDirectReportRateSupported(sensor, rate)) {
+        return;
+    }
+
+    if (!isDirectChannelTypeSupported(sensor, memType)) {
+        return;
+    }
+
+    std::unique_ptr<SensorsTestSharedMemory> mem(
+        SensorsTestSharedMemory::create(memType, 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, rate,
+                       [&eventToken](auto result, auto token) {
+                           ASSERT_EQ(result, Result::OK);
+                           eventToken = token;
+                       });
+
+    usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
+    auto events = mem->parseEvents();
+
+    // find norminal rate
+    float nominalFreq = 0.f;
+    switch (rate) {
+        case RateLevel::NORMAL:
+            nominalFreq = kNormalNominal;
+            break;
+        case RateLevel::FAST:
+            nominalFreq = kFastNominal;
+            break;
+        case RateLevel::VERY_FAST:
+            nominalFreq = kVeryFastNominal;
+            break;
+        case RateLevel::STOP:
+            FAIL();
+    }
+
+    // allowed to be between 55% and 220% of nominal freq
+    ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
+    ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
+
+    int64_t lastTimestamp = 0;
+    bool typeErrorReported = false;
+    bool tokenErrorReported = false;
+    bool timestampErrorReported = false;
+    std::vector<Event> sensorEvents;
+    for (auto& e : events) {
+        if (!tokenErrorReported) {
+            EXPECT_EQ(eventToken, e.sensorHandle)
+                << (tokenErrorReported = true,
+                    "Event token does not match that retured from configDirectReport");
+        }
+
+        if (isMetaSensorType(e.sensorType)) {
+            continue;
+        }
+        sensorEvents.push_back(e);
+
+        if (!typeErrorReported) {
+            EXPECT_EQ(type, e.sensorType)
+                << (typeErrorReported = true,
+                    "Type in event does not match type of sensor registered.");
+        }
+        if (!timestampErrorReported) {
+            EXPECT_GT(e.timestamp, lastTimestamp)
+                << (timestampErrorReported = true, "Timestamp not monotonically increasing");
+        }
+        lastTimestamp = e.timestamp;
+    }
+
+    std::string s;
+    EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+    // stop sensor and unregister channel
+    configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
+                       [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
+    EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
+}
+
+void SensorsHidlTestBase::testStreamingOperation(SensorType type,
+                                                 std::chrono::nanoseconds samplingPeriod,
+                                                 std::chrono::seconds duration,
+                                                 const SensorEventsChecker& checker) {
+    std::vector<Event> events;
+    std::vector<Event> sensorEvents;
+
+    const int64_t samplingPeriodInNs = samplingPeriod.count();
+    const int64_t batchingPeriodInNs = 0;  // no batching
+    const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
+    const size_t minNEvent = duration / samplingPeriod;
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
+        // rate not supported
+        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);
+
+    bool handleMismatchReported = false;
+    bool metaSensorTypeErrorReported = false;
+    for (auto& e : events) {
+        if (e.sensorType == type) {
+            // avoid generating hundreds of error
+            if (!handleMismatchReported) {
+                EXPECT_EQ(e.sensorHandle, handle)
+                    << (handleMismatchReported = true,
+                        "Event of the same type must come from the sensor registered");
+            }
+            sensorEvents.push_back(e);
+        } else {
+            // avoid generating hundreds of error
+            if (!metaSensorTypeErrorReported) {
+                EXPECT_TRUE(isMetaSensorType(e.sensorType))
+                    << (metaSensorTypeErrorReported = true,
+                        "Only meta types are allowed besides the type registered");
+            }
+        }
+    }
+
+    std::string s;
+    EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+    EXPECT_GE(sensorEvents.size(),
+              minNEvent / 2);  // make sure returned events are not all meta
+}
+
+void SensorsHidlTestBase::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
+    std::vector<Event> events1, events2;
+
+    constexpr int64_t batchingPeriodInNs = 0;          // no batching
+    constexpr int64_t collectionTimeoutUs = 60000000;  // 60s
+    constexpr size_t minNEvent = 50;
+
+    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;
+    }
+
+    int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+    int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+
+    // first collection
+    ASSERT_EQ(batch(handle, firstCollectionPeriod, 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(collectionTimeoutUs, minNEvent);
+
+    // second collection, without stop sensor
+    ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
+
+    usleep(500000);  // sleep 0.5 sec to wait for change rate to happen
+    events2 = collectEvents(collectionTimeoutUs, minNEvent);
+
+    // end of collection, stop sensor
+    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;
+    std::vector<Event>& minDelayEvents(fastToSlow ? events1 : events2);
+    std::vector<Event>& maxDelayEvents(fastToSlow ? events2 : events1);
+
+    size_t nEvent = 0;
+    int64_t prevTimestamp = -1;
+    int64_t timestampInterval = 0;
+    for (auto& e : minDelayEvents) {
+        if (e.sensorType == type) {
+            ASSERT_EQ(e.sensorHandle, handle);
+            if (prevTimestamp > 0) {
+                timestampInterval += e.timestamp - prevTimestamp;
+            }
+            prevTimestamp = e.timestamp;
+            ++nEvent;
+        }
+    }
+    ASSERT_GT(nEvent, 2u);
+    minDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+    nEvent = 0;
+    prevTimestamp = -1;
+    timestampInterval = 0;
+    for (auto& e : maxDelayEvents) {
+        if (e.sensorType == type) {
+            ASSERT_EQ(e.sensorHandle, handle);
+            if (prevTimestamp > 0) {
+                timestampInterval += e.timestamp - prevTimestamp;
+            }
+            prevTimestamp = e.timestamp;
+            ++nEvent;
+        }
+    }
+    ASSERT_GT(nEvent, 2u);
+    maxDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+    // change of rate is significant.
+    ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval,
+          maxDelayAverageInterval);
+    EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
+
+    // fastest rate sampling time is close to spec
+    EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+              minSamplingPeriodInNs / 10);
+
+    // slowest rate sampling time is close to spec
+    EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
+              maxSamplingPeriodInNs / 10);
+}
+
+void SensorsHidlTestBase::testBatchingOperation(SensorType type) {
+    std::vector<Event> events;
+
+    constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
+    constexpr int64_t oneSecondInNs = 1ull * 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);
+
+    getEnvironment()->setCollection(true);
+    // clean existing collections
+    collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
+                  false /*change collection*/);
+
+    // 0.8 + 0.2 times the batching period
+    usleep(batchingPeriodInNs / 1000 * 8 / 10);
+    ASSERT_EQ(flush(handle), Result::OK);
+
+    // plus some time for the event to deliver
+    events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
+                           false /*clearBeforeStart*/, false /*change collection*/);
+
+    getEnvironment()->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)(minFifoCount * 9 / 10));
+}
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
new file mode 100644
index 0000000..5096498
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SensorsTestSharedMemory.h"
+
+#include <log/log.h>
+
+#include <sys/mman.h>
+#include <cinttypes>
+
+using namespace ::android::hardware::sensors::V1_0;
+
+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) {
+            ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, 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 %" PRId64 ", 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;
+        }
+        case SharedMemType::GRALLOC: {
+            mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
+            if (mGrallocWrapper->getAllocator() == nullptr ||
+                mGrallocWrapper->getMapper() == nullptr) {
+                break;
+            }
+            using android::hardware::graphics::common::V1_0::BufferUsage;
+            using android::hardware::graphics::common::V1_0::PixelFormat;
+            mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
+                .width = static_cast<uint32_t>(size),
+                .height = 1,
+                .layerCount = 1,
+                .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
+                                               BufferUsage::CPU_READ_OFTEN),
+                .format = PixelFormat::BLOB};
+
+            handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
+            if (handle != nullptr) {
+                mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
+                                              static_cast<int32_t>(buf_desc_info.height)};
+                buffer = static_cast<char*>(
+                    mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
+                if (buffer != nullptr) {
+                    break;
+                }
+                mGrallocWrapper->freeBuffer(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;
+        }
+        case SharedMemType::GRALLOC: {
+            if (mSize != 0) {
+                mGrallocWrapper->unlock(mNativeHandle);
+                mGrallocWrapper->freeBuffer(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;
+}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
new file mode 100644
index 0000000..3bd73c3
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -0,0 +1,79 @@
+/*
+ * 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 GRALLO_WRAPPER_H_
+#define GRALLO_WRAPPER_H_
+
+#include <unordered_set>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
+namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
+
+namespace android {
+
+// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
+class GrallocWrapper {
+   public:
+    GrallocWrapper();
+    ~GrallocWrapper();
+
+    sp<allocator2::IAllocator> getAllocator() const;
+    sp<mapper2::IMapper> getMapper() const;
+
+    std::string dumpDebugInfo();
+
+    // When import is false, this simply calls IAllocator::allocate. When import
+    // is true, the returned buffers are also imported into the mapper.
+    //
+    // Either case, the returned buffers must be freed with freeBuffer.
+    std::vector<const native_handle_t*> allocate(const mapper2::BufferDescriptor& descriptor,
+                                                 uint32_t count, bool import = true,
+                                                 uint32_t* outStride = nullptr);
+    const native_handle_t* allocate(const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import = true, uint32_t* outStride = nullptr);
+
+    mapper2::BufferDescriptor createDescriptor(
+        const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
+
+    const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
+    void freeBuffer(const native_handle_t* bufferHandle);
+
+    // We use fd instead of hardware::hidl_handle in these functions to pass fences
+    // in and out of the mapper.  The ownership of the fd is always transferred
+    // with each of these functions.
+    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const mapper2::IMapper::Rect& accessRegion, int acquireFence);
+
+    int unlock(const native_handle_t* bufferHandle);
+
+   private:
+    void init();
+    const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
+
+    sp<allocator2::IAllocator> mAllocator;
+    sp<mapper2::IMapper> mMapper;
+
+    // Keep track of all cloned and imported handles.  When a test fails with
+    // ASSERT_*, the destructor will free the handles for the test.
+    std::unordered_set<const native_handle_t*> mClonedBuffers;
+    std::unordered_set<const native_handle_t*> mImportedBuffers;
+};
+
+}  // namespace android
+#endif  // GRALLO_WRAPPER_H_
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
new file mode 100644
index 0000000..b5daccc
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSOR_EVENTS_CHECKER_H
+#define ANDROID_SENSOR_EVENTS_CHECKER_H
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cmath>
+
+class SensorEventsChecker {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    virtual bool check(const std::vector<Event>& events, std::string* out) const = 0;
+    virtual ~SensorEventsChecker() {}
+};
+
+class NullChecker : public SensorEventsChecker {
+   public:
+    virtual bool check(const std::vector<Event>&, std::string*) const { return true; }
+};
+
+class SensorEventPerEventChecker : public SensorEventsChecker {
+   public:
+    virtual bool checkEvent(const Event& event, std::string* out) const = 0;
+    virtual bool check(const std::vector<Event>& events, std::string* out) const {
+        for (const auto& e : events) {
+            if (!checkEvent(e, out)) {
+                return false;
+            }
+        }
+        return true;
+    }
+};
+
+class Vec3NormChecker : public SensorEventPerEventChecker {
+   public:
+    Vec3NormChecker(float min, float max) : mLowerLimit(min), mUpperLimit(max) {}
+    static Vec3NormChecker byNominal(float nominal, float allowedError) {
+        return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
+    }
+
+    virtual bool checkEvent(const Event& event, std::string* out) const {
+        android::hardware::sensors::V1_0::Vec3 v = event.u.vec3;
+        float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+        if (norm < mLowerLimit || norm > mUpperLimit) {
+            if (out != nullptr) {
+                std::ostringstream ss;
+                ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z
+                   << ")"
+                   << " has norm " << norm << ", which is beyond range"
+                   << " [" << mLowerLimit << ", " << mUpperLimit << "]";
+                *out = ss.str();
+            }
+            return false;
+        }
+        return true;
+    }
+
+   protected:
+    float mLowerLimit;
+    float mUpperLimit;
+};
+
+#endif  // ANDROID_SENSOR_EVENTS_CHECKER_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
new file mode 100644
index 0000000..96e6085
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    virtual void HidlSetUp() override;
+    virtual void HidlTearDown() override;
+
+    // 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);
+
+   protected:
+    SensorsHidlEnvironmentBase() {}
+
+    void addEvent(const Event& ev);
+
+    virtual void startPollingThread() = 0;
+    virtual bool resetHal() = 0;
+
+    bool collectionEnabled;
+    std::atomic_bool stopThread;
+    std::thread pollThread;
+    std::vector<Event> events;
+    std::mutex events_mutex;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
new file mode 100644
index 0000000..f4b259f
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_TEST_BASE_H
+#define ANDROID_SENSORS_HIDL_TEST_BASE_H
+
+#include "sensors-vts-utils/SensorEventsChecker.h"
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <unordered_set>
+#include <vector>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::ISensors;
+using ::android::hardware::sensors::V1_0::RateLevel;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorFlagBits;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::sensors::V1_0::SharedMemInfo;
+using ::android::hardware::sensors::V1_0::SharedMemType;
+
+class SensorsHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual SensorsHidlEnvironmentBase* getEnvironment() = 0;
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override {
+        // stop all sensors
+        for (auto s : mSensorHandles) {
+            activate(s, false);
+        }
+        mSensorHandles.clear();
+
+        // stop all direct report and channels
+        for (auto c : mDirectChannelHandles) {
+            // disable all reports
+            configDirectReport(-1, c, RateLevel::STOP, [](auto, auto) {});
+            unregisterDirectChannel(c);
+        }
+        mDirectChannelHandles.clear();
+    }
+
+    // implementation wrapper
+    virtual SensorInfo defaultSensorByType(SensorType type) = 0;
+    virtual Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) = 0;
+
+    virtual Return<Result> activate(int32_t sensorHandle, bool enabled) = 0;
+
+    virtual Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                                 int64_t maxReportLatencyNs) = 0;
+
+    virtual Return<Result> flush(int32_t sensorHandle) = 0;
+    virtual Return<Result> injectSensorData(const Event& event) = 0;
+    virtual Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                               ISensors::registerDirectChannel_cb _hidl_cb) = 0;
+    virtual Return<Result> unregisterDirectChannel(int32_t channelHandle) = 0;
+    virtual Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle,
+                                            RateLevel rate,
+                                            ISensors::configDirectReport_cb _hidl_cb) = 0;
+
+    std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+                                     bool clearBeforeStart = true, bool changeCollection = true);
+
+    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; }
+
+    void testStreamingOperation(SensorType type, std::chrono::nanoseconds samplingPeriod,
+                                std::chrono::seconds duration, const SensorEventsChecker& checker);
+    void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
+    void testBatchingOperation(SensorType type);
+    void testDirectReportOperation(SensorType type, SharedMemType memType, RateLevel rate,
+                                   const SensorEventsChecker& checker);
+
+    static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
+    static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
+    static void assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+                                           SensorFlagBits reportMode);
+    static SensorFlagBits expectedReportModeForType(SensorType type);
+    static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
+    static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
+
+   protected:
+    // checkers
+    static const Vec3NormChecker sAccelNormChecker;
+    static const Vec3NormChecker sGyroNormChecker;
+
+    // all sensors and direct channnels used
+    std::unordered_set<int32_t> mSensorHandles;
+    std::unordered_set<int32_t> mDirectChannelHandles;
+};
+
+#endif  // ANDROID_SENSORS_HIDL_TEST_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
new file mode 100644
index 0000000..055b8e7
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+#define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+
+#include "GrallocWrapper.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cutils/ashmem.h>
+
+class SensorsTestSharedMemory {
+    using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType;
+    using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+    using Event = ::android::hardware::sensors::V1_0::Event;
+
+   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;
+    std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
+
+    DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
+};
+
+#endif  // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
diff --git a/tests/bar/1.0/default/Bar.cpp b/tests/bar/1.0/default/Bar.cpp
index 4614428..0a57b40 100644
--- a/tests/bar/1.0/default/Bar.cpp
+++ b/tests/bar/1.0/default/Bar.cpp
@@ -149,6 +149,10 @@
     return mFoo->closeHandles();
 }
 
+Return<void> Bar::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+    return mFoo->repeatWithFmq(withFmq, _hidl_cb);
+}
+
 Return<void> Bar::echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) {
     return mFoo->echoNullInterface(cb, _hidl_cb);
 }
diff --git a/tests/bar/1.0/default/Bar.h b/tests/bar/1.0/default/Bar.h
index acb976f..4372266 100644
--- a/tests/bar/1.0/default/Bar.h
+++ b/tests/bar/1.0/default/Bar.h
@@ -56,6 +56,8 @@
     virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb)  override;
     virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb)  override;
     virtual Return<void> closeHandles()  override;
+    virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+                                       repeatWithFmq_cb _hidl_cb) override;
 
     Return<void> haveAVectorOfInterfaces(
             const hidl_vec<sp<ISimple> > &in,
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 8118d8b..91ed1f2 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -36,6 +36,17 @@
     typedef SomeOtherEnum thisIsAnAlias;
     typedef IBaz anIBazByAnyOtherName;
 
+    struct NastyNester {
+        struct NestersNasty {
+            struct NestersNastyNester {
+                IBaz baz;
+                vec<NestersNasty> nasties;
+            };
+        };
+
+        IBaz baz;
+    };
+
     enum SomeEnum : SomeOtherEnum {
         quux = 33,
         goober = 192,
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4a930a2..4c54427 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -103,7 +103,6 @@
         union U {
             int8_t number;
             int8_t[1][2] multidimArray;
-            pointer p;
             Fumble anotherStruct;
             bitfield<BitField> bf;
         } u;
@@ -122,6 +121,17 @@
         bitfield<BitField> bf;
     };
 
+    struct WithFmq {
+        struct ScatterGather {
+            fmq_sync<uint8_t> descSync;
+        } scatterGathered;
+
+        struct ContainsPointer {
+            fmq_sync<uint8_t> descSync;
+            interface foo;
+        } containsPointer;
+    };
+
     enum Discriminator : uint8_t {
         BOOL,
         INT,
@@ -205,4 +215,6 @@
     createMyHandle() generates (MyHandle h);
     createHandles(uint32_t size) generates (vec<handle> handles);
     closeHandles();
+
+    repeatWithFmq(WithFmq withFmq) generates (WithFmq withFmq);
 };
diff --git a/tests/foo/1.0/default/Foo.cpp b/tests/foo/1.0/default/Foo.cpp
index a31ab9f..461568b 100644
--- a/tests/foo/1.0/default/Foo.cpp
+++ b/tests/foo/1.0/default/Foo.cpp
@@ -379,6 +379,11 @@
     return Void();
 }
 
+Return<void> Foo::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+    _hidl_cb(withFmq);
+    return Void();
+}
+
 IFoo* HIDL_FETCH_IFoo(const char* /* name */) {
     return new Foo();
 }
diff --git a/tests/foo/1.0/default/Foo.h b/tests/foo/1.0/default/Foo.h
index 7dd672b..d73179a 100644
--- a/tests/foo/1.0/default/Foo.h
+++ b/tests/foo/1.0/default/Foo.h
@@ -53,6 +53,8 @@
     virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb)  override;
     virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb)  override;
     virtual Return<void> closeHandles()  override;
+    virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+                                       repeatWithFmq_cb _hidl_cb) override;
 
     Return<void> haveAVectorOfInterfaces(
             const hidl_vec<sp<ISimple> > &in,
@@ -63,6 +65,7 @@
             haveAVectorOfGenericInterfaces_cb _hidl_cb) override;
 
     Return<void> echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) override;
+
 private:
     std::vector<::native_handle_t *> mHandles;
 };
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
index ede8401..87edd53 100644
--- a/tests/safeunion/1.0/Android.bp
+++ b/tests/safeunion/1.0/Android.bp
@@ -9,6 +9,7 @@
     ],
     interfaces: [
         "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
     ],
     gen_java: true,
 }
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
index f48248b..58c08c6 100644
--- a/tests/safeunion/1.0/ISafeUnion.hal
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -18,6 +18,8 @@
 
 import IOtherInterface;
 
+import android.hidl.safe_union@1.0::Monostate;
+
 interface ISafeUnion {
 
     enum BitField : uint8_t {
@@ -33,14 +35,15 @@
         string j3;
     };
 
-    safe_union EmptySafeUnion {
-    };
-
     safe_union SmallSafeUnion {
+        Monostate noinit;
+
         uint8_t a;
     };
 
     safe_union LargeSafeUnion {
+        Monostate noinit;
+
         int8_t a;
         uint16_t b;
         int32_t c;
@@ -66,6 +69,8 @@
     };
 
     safe_union InterfaceTypeSafeUnion {
+        Monostate noinit;
+
         uint32_t a;
         int8_t[7] b;
         IOtherInterface c;
@@ -76,6 +81,8 @@
     };
 
     safe_union HandleTypeSafeUnion {
+        Monostate noinit;
+
         handle a;
         handle[5] b;
         vec<handle> c;
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 6522f4d..d0dd915 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -45,6 +45,8 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
 }
 
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index a341028..a22cd72 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/wifi/1.0/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -143,6 +144,14 @@
         return;
     }
 
+    sp<::android::hardware::wifi::V1_3::IWifiStaIface> iface_converted =
+        ::android::hardware::wifi::V1_3::IWifiStaIface::castFrom(
+            wifi_sta_iface_);
+    if (iface_converted != nullptr) {
+        // Skip this test since this API is deprecated in this newer HAL version
+        return;
+    }
+
     // Enable link layer stats collection.
     EXPECT_EQ(WifiStatusCode::SUCCESS,
               HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 2d9050d..61060b5 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -204,6 +204,19 @@
         }
     }
 
+    bool createRttController() {
+        bool success = false;
+        chip_->createRttController(
+            NULL, [&success](const WifiStatus& status,
+                             const sp<IWifiRttController>& rtt) {
+                if (WifiStatusCode::SUCCESS == status.code) {
+                    ASSERT_NE(rtt.get(), nullptr);
+                    success = true;
+                }
+            });
+        return success;
+    }
+
    public:
     void SetUp() override {
         chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
@@ -386,6 +399,29 @@
     ASSERT_TRUE(createIface(IfaceType::NAN).empty());
 }
 
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    const auto ap_iface_name = createIface(IfaceType::AP);
+    ASSERT_FALSE(ap_iface_name.empty());
+    ASSERT_FALSE(createRttController());
+
+    removeIface(IfaceType::AP, ap_iface_name);
+
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
 ////////// V2 + Aware Iface Combinations ////////////
 // Mode 1 - STA + STA/AP
 //        - STA + P2P/NAN
@@ -540,6 +576,24 @@
     ASSERT_NE(sta_iface_name, ap_iface_name);
 }
 
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_TRUE(createRttController());
+}
+
 ////////// V1 Iface Combinations when AP creation is disabled //////////
 class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
    public:
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index cf64e51..faf1862 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -930,6 +930,12 @@
 
 std::pair<WifiStatus, sp<IWifiRttController>>
 WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
+    if (sta_ifaces_.size() == 0 &&
+        !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+        LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
+                      "(and RTT by extension)";
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
     sp<WifiRttController> rtt =
         new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);