Merge "Add portMode configuration test" into oc-mr1-dev
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 5b31d1e..dd4cee0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -61,3 +61,5 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/android.hardware.automotive*)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.hardware.automotive*)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/android.hardware.tests*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/android.hardware.tests*)
diff --git a/audio/2.0/config/audio_policy_configuration.xsd b/audio/2.0/config/audio_policy_configuration.xsd
index c94da80..eb59152 100644
--- a/audio/2.0/config/audio_policy_configuration.xsd
+++ b/audio/2.0/config/audio_policy_configuration.xsd
@@ -365,10 +365,10 @@
         </xs:restriction>
     </xs:simpleType>
     <xs:complexType name="profile">
-        <xs:attribute name="name" type="xs:token" use="required"/>
-        <xs:attribute name="format" type="audioFormat" use="required"/>
-        <xs:attribute name="samplingRates" type="samplingRates" use="required"/>
-        <xs:attribute name="channelMasks" type="channelMask" use="required"/>
+        <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">
diff --git a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
index 5fc1b3d..ee49023 100644
--- a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
+++ b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
@@ -24,13 +24,9 @@
     const char* possibleConfigLocations[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
     const char* configSchemaPath = "/data/local/tmp/audio_policy_configuration.xsd";
 
-    bool found = false;
     for (std::string folder : possibleConfigLocations) {
         const auto configPath = folder + '/' + configName;
         if (access(configPath.c_str(), R_OK) == 0) {
-            ASSERT_FALSE(found) << "Multiple " << configName << " found in "
-                                << ::testing::PrintToString(possibleConfigLocations);
-            found = true;
             ASSERT_VALID_XML(configPath.c_str(), configSchemaPath);
         }
     }
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 385f03d..6bc0522 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
@@ -162,12 +162,29 @@
     return StatusCode::OK;
 }
 
+static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
+    switch (propConfig.prop) {
+        case OBD2_LIVE_FRAME:
+        case OBD2_FREEZE_FRAME:
+        case OBD2_FREEZE_FRAME_CLEAR:
+        case OBD2_FREEZE_FRAME_INFO:
+            return true;
+    }
+    return false;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t supportedAreas = cfg.supportedAreas;
 
+        if (isDiagnosticProperty(cfg)) {
+            // do not write an initial empty value for the diagnostic properties
+            // as we will initialize those separately.
+            continue;
+        }
+
         //  A global property will have supportedAreas = 0
         if (isGlobalProp(cfg.prop)) {
             supportedAreas = 0;
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 12b92dd..7c08b4a 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -785,7 +785,8 @@
      * requested by Android side. The focus has both per stream characteristics
      * and global characteristics.
      *
-     * Focus request (get of this property) must take the following form:
+     * Focus request (get of this property) must take the following form with indices defined
+     * by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusRequest type
      *   int32Values[1]: bit flags of streams requested by this focus request.
      *                   There can be up to 32 streams.
@@ -803,7 +804,7 @@
      *                   REQUEST_RELEASE). In that case, audio module must
      *                   maintain mute state until user's explicit action to
      *                   play some media.
-     *   int32Values[3]: Currently active audio contexts. Use combination of
+     *   int32Values[3]: Audio contexts wishing to be active. Use combination of
      *                   flags from VehicleAudioContextFlag.
      *                   This can be used as a hint to adjust audio policy or
      *                   other policy decision.
@@ -818,7 +819,7 @@
      * request.
      *
      * Focus response (set and subscription callback for this property) must
-     * take the following form:
+     * take the following form with indices defined by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusState type
      *   int32Values[1]: bit flags of streams allowed.
      *   int32Values[2]: External focus state: bit flags of currently active
@@ -847,9 +848,10 @@
      *                       side is playing something permanent.
      *                   LOSS_TRANSIENT: must always be
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
-     *   int32Values[3]: context requested by android side when responding to
-     *                   focus request. When car side is taking focus away,
-     *                   this must be zero.
+     *   int32Values[3]: Audio context(s) allowed to be active. When responding positively to a
+     *                   focus request from Android, the request's original context must be
+     *                   repeated here. When taking focus away, or denying a request, the
+     *                   rejected or stopped context would have its corresponding bit cleared.
      *
      * A focus response must be sent per each focus request even if there is
      * no change in focus state. This can happen in case like focus request
@@ -890,8 +892,8 @@
      *
      * VehiclePropConfig
      *   configArray[0] : bit flags of all supported audio contexts from
-     *                    VehicleAudioContextFlag. If this is 0, audio volume is
-     *                    controlled per physical stream.
+     *                    VehicleAudioContextFlag. If this is 0, audio volume
+     *                    is controlled per physical stream.
      *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
      *                    represent audio module's capability.
      *   configArray[2..3] : reserved
@@ -901,7 +903,7 @@
      *                         indicates mute state.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioContextFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
@@ -909,8 +911,8 @@
      *                    defined in the config.
      *   int32Values[2] : One of VehicleAudioVolumeState.
      *
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -949,18 +951,18 @@
      *                    to represent audio module's capability.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioContextFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
      *   int32Values[1] : maximum volume set to the stream. If there is no
-     *                    restriction, this value must be bigger than
+     *                    restriction, this value must be equal to
      *                    AUDIO_VOLUME's max value.
      *
      * If car does not support this feature, this property must not be
      * populated by HAL.
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -974,10 +976,8 @@
 
     /**
      * Property to share audio routing policy of android side. This property is
-     * set at the beginning to pass audio policy in android side down to
+     * set at startup to pass audio policy in android side down to
      * vehicle HAL and car audio module.
-     * This can be used as a hint to adjust audio policy or other policy
-     * decision.
      *
      *   int32Values[0] : audio stream where the audio for the application
      *                    context must be routed by default. Note that this is
@@ -1001,11 +1001,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to return audio H/W variant type used in this car. This allows
-     * android side to support different audio policy based on H/W variant used.
-     * Note that other components like CarService may need overlay update to
-     * support additional variants. If this property does not
-     * exist, default audio policy must be used.
+     * Property to return audio H/W variant type used in this car. This is a
+     * zero based index into the set of audio routing policies defined in
+     * R.array.audioRoutingPolicy on CarService, which  may be overlaid to
+     * support multiple variants. If this property does not exist, the default
+     * audio policy must be used.
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -2224,6 +2224,9 @@
 
     /** Ext source is played. This is for tagging generic ext sources. */
     EXT_SOURCE_FLAG = 0x1000,
+
+    /** The phone ring tone is played */
+    RINGTONE_FLAG = 0x2000
 };
 
 /**
@@ -2232,23 +2235,23 @@
  */
 enum VehicleAudioVolumeCapabilityFlag : int32_t {
     /**
-     * External audio module or vehicle hal has persistent storage
-     * to keep the volume level. This must be set only when per context
-     * volume level is supported. When this is set, audio volume level per
-     * each context will be retrieved from the property when system starts up.
+     * External audio module or vehicle hal has persistent storage to keep the
+     * volume level. When this is set, the audio volume level for each context
+     * will be retrieved from the property when the system starts up.
      * And external audio module is also expected to adjust volume automatically
      * whenever there is an audio context change.
      * When this flag is not set, android side will assume that there is no
-     * persistent storage and stored value in android side will be used to
-     * initialize the volume level. And android side will set volume level
-     * of each physical streams whenever there is an audio context change.
+     * persistent storage and the value stored in the android side will be used to
+     * initialize the volume level, and android side will set volume level
+     * of each physical stream whenever there is an audio context change.
      */
     PERSISTENT_STORAGE = 0x1,
 
     /**
+     * [DEPRECATED]
      * When this flag is set, the H/W can support only single master volume for
-     * all streams.
-     * There is no way to set volume level differently per each stream or context.
+     * all streams. There is no way to set volume level differently for each stream
+     * or context.
      */
     MASTER_VOLUME_ONLY = 0x2,
 };
@@ -2264,16 +2267,16 @@
      * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
      * further is not allowed.
      */
-    LIMIT_REACHED = 1,
+    STATE_LIMIT_REACHED = 1,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
  */
 enum VehicleAudioVolumeIndex : int32_t {
-    INDEX_STREAM = 0,
-    INDEX_VOLUME = 1,
-    INDEX_STATE = 2,
+    STREAM = 0,
+    VOLUME = 1,
+    STATE = 2,
 };
 
 /**
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index fb53366..6c9aa18 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -464,8 +464,9 @@
 
 // Return the number of completed packets reported by the controller.
 int BluetoothHidlTest::wait_for_completed_packets_event(uint16_t handle) {
-    EXPECT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived)
-                    .no_timeout);
+    if (!bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived).no_timeout) {
+        ALOGW("%s: WaitForCallback timed out.", __func__);
+    }
     int packets_processed = 0;
     while (event_queue.size() > 0) {
         hidl_vec<uint8_t> event = event_queue.front();
@@ -604,20 +605,24 @@
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(1, max_sco_data_packet_length, sco_connection_handles[0]);
-    sco_packets_sent = 1;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(1, max_acl_data_packet_length, acl_connection_handles[0]);
-    acl_packets_sent = 1;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
@@ -633,22 +638,26 @@
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(NUM_SCO_PACKETS_BANDWIDTH, max_sco_data_packet_length,
                     sco_connection_handles[0]);
-    sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(NUM_ACL_PACKETS_BANDWIDTH, max_acl_data_packet_length,
                     acl_connection_handles[0]);
-    acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
diff --git a/compatibility_matrix.26.xml b/compatibility_matrix.26.xml
index c9b68a8..5c81f26 100644
--- a/compatibility_matrix.26.xml
+++ b/compatibility_matrix.26.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -204,16 +212,24 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -256,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -281,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -289,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -304,14 +336,30 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
diff --git a/compatibility_matrix.27.xml b/compatibility_matrix.27.xml
new file mode 100644
index 0000000..5c81f26
--- /dev/null
+++ b/compatibility_matrix.27.xml
@@ -0,0 +1,370 @@
+<compatibility-matrix version="1.0" type="framework">
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>2.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <instance>legacy/0</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.configstore</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISurfaceFlingerConfigs</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.0</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <version>2.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>2.0</version>
+        <interface>
+            <name>ILight</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.0</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+        </interface>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.deprecated</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemHook</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index 8d50325..5c81f26 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -206,10 +214,14 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.power</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -217,7 +229,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -260,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -285,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -293,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -310,16 +338,28 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.weaver</name>
         <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
diff --git a/compatibility_matrix.legacy.xml b/compatibility_matrix.legacy.xml
index ad6d4b9..5655fb9 100644
--- a/compatibility_matrix.legacy.xml
+++ b/compatibility_matrix.legacy.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -204,16 +212,24 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -256,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -281,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -289,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -304,14 +336,30 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
diff --git a/current.txt b/current.txt
index c0dd0fa..f045fd8 100644
--- a/current.txt
+++ b/current.txt
@@ -189,7 +189,7 @@
 
 # ABI preserving changes to HALs during Android O MR1 (Initial Set)
 
-05e0edf31db5b3ae19047d87059545cc2f836023edf8f9d969319e15e3485158 android.hardware.automotive.vehicle@2.0::types
+26a4dd19a71f3a28249100af29be470f80e08355165fe6a7173aaa1ef264640d android.hardware.automotive.vehicle@2.0::types
 150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
 dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
 760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index 9ee5f4f..058709c 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -92,6 +92,23 @@
     bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
             hidl_vec<hidl_handle>* outCommandHandles)
     {
+        // After data are written to the queue, it may not be read by the
+        // remote reader when
+        //
+        //  - the writer does not send them (because of other errors)
+        //  - the hwbinder transaction fails
+        //  - the reader does not read them (because of other errors)
+        //
+        // Discard the stale data here.
+        size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
+        if (staleDataSize > 0) {
+            ALOGW("discarding stale data from message queue");
+            CommandQueueType::MemTransaction tx;
+            if (mQueue->beginRead(staleDataSize, &tx)) {
+                mQueue->commitRead(staleDataSize);
+            }
+        }
+
         // write data to queue, optionally resizing it
         if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
             if (!mQueue->write(mData.get(), mDataWritten)) {
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 18955da..9a749d7 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -23,6 +23,7 @@
 #include "VtsHalGraphicsMapperTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <unistd.h>
 
 #include <algorithm>
@@ -703,10 +704,11 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-
-  return status;
+    using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 6790ebf..8520757 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -765,13 +765,13 @@
     int bytesCount = 0;
     uint32_t flags = 0;
     uint32_t timestamp = 0;
-    timestampDevTest = true;
+    timestampDevTest = false;
     while (1) {
         if (!(eleInfo >> bytesCount)) break;
         eleInfo >> flags;
         eleInfo >> timestamp;
         Info.push_back({bytesCount, flags, timestamp});
-        if (flags != OMX_BUFFERFLAG_CODECCONFIG)
+        if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
             timestampUslist.push_back(timestamp);
     }
     eleInfo.close();
@@ -813,7 +813,7 @@
     packedArgs audioArgs = {eEncoding, compName};
     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, nullptr,
             portReconfiguration, kPortIndexInput, kPortIndexOutput, &audioArgs);
-    EXPECT_EQ(timestampUslist.empty(), true);
+    if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
     // set state to idle
     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
     // set state to executing
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 37d9956..2ec86b2 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -371,7 +371,7 @@
         kPortIndexOutput = kPortIndexInput + 1;
     }
 
-    for (size_t i = kPortIndexInput; i < kPortIndexOutput; i++) {
+    for (size_t i = kPortIndexInput; i <= kPortIndexOutput; i++) {
         OMX_PARAM_PORTDEFINITIONTYPE portDef;
         status =
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
@@ -406,10 +406,32 @@
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
             portDef = mirror;
-            portDef.nBufferSize >>= 1;
+            OMX_U32 nBufferSize = portDef.nBufferSize >> 1;
+            if (nBufferSize != 0) {
+                if (!strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11)) {
+                    portDef.nBufferSize = nBufferSize;
+                } else {
+                    // Probable alignment requirements of vendor component
+                    portDef.nBufferSize = ALIGN_POWER_OF_TWO(nBufferSize, 12);
+                    nBufferSize = portDef.nBufferSize;
+                }
+            } else {
+                ASSERT_TRUE(false) << "Unexpected buffer size";
+            }
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
-            EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
+            // SPECIAL CASE: For video decoder, allow configuration of input
+            // buffer size even if it is less than minimum requirement and
+            // similarly for encoder allow configuration of output port buffer
+            // size.
+            if ((compClass == video_encoder && i == kPortIndexOutput) ||
+                (compClass == video_decoder && i == kPortIndexInput)) {
+                double dev = (portDef.nBufferSize / (double)nBufferSize);
+                dev -= 1;
+                if (dev < 0 || dev > 0.1) EXPECT_TRUE(false);
+            } else {
+                EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
+            }
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
             portDef = mirror;
@@ -467,6 +489,11 @@
         portBase = params.nStartPortNumber;
     }
 
+    // set state to idle
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateIdle);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
     status =
         getPortParam(omxNode, OMX_IndexParamPortDefinition, portBase, &portDef);
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index c75bd7c..1d4fd67 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -498,6 +498,21 @@
         ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
         if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
             msg.data.eventData.data2 == 0) {
+            // Components can send various kinds of port settings changed events
+            // all at once. Before committing to a full port reconfiguration,
+            // defer any events waiting in the queue to be addressed to a later
+            // point.
+            android::List<Message> msgQueueDefer;
+            while (1) {
+                status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+                                                  iBuffer, oBuffer);
+                if (status !=
+                    android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
+                    msgQueueDefer.push_back(msg);
+                    continue;
+                } else
+                    break;
+            }
             status = omxNode->sendCommand(
                 toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -577,6 +592,16 @@
                 ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
                 ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
 
+                // Push back deferred messages to the list
+                android::List<Message>::iterator it = msgQueueDefer.begin();
+                while (it != msgQueueDefer.end()) {
+                    status = omxNode->dispatchMessage(*it);
+                    ASSERT_EQ(
+                        status,
+                        ::android::hardware::media::omx::V1_0::Status::OK);
+                    it++;
+                }
+
                 // dispatch output buffers
                 for (size_t i = 0; i < oBuffer->size(); i++) {
                     dispatchOutputBuffer(omxNode, oBuffer, i, oPortMode);
@@ -906,7 +931,7 @@
         eleInfo >> flags;
         eleInfo >> timestamp;
         Info.push_back({bytesCount, flags, timestamp});
-        if (flags != OMX_BUFFERFLAG_CODECCONFIG)
+        if (timestampDevTest && (flags != OMX_BUFFERFLAG_CODECCONFIG))
             timestampUslist.push_back(timestamp);
         if (maxBytesCount < bytesCount) maxBytesCount = bytesCount;
     }
@@ -980,7 +1005,7 @@
                            kPortIndexInput, kPortIndexOutput, portMode[1]);
     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag, portMode,
             portReconfiguration, kPortIndexInput, kPortIndexOutput, nullptr);
-    EXPECT_EQ(timestampUslist.empty(), true);
+    if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
     // set state to idle
     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
     // set state to executing
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index f4a4e9b..23f051d 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -1300,7 +1300,7 @@
     eleStream.close();
     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer);
     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
-    EXPECT_EQ(timestampUslist.empty(), true);
+    if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
 
     // set state to idle
     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index b5603a2..d7c3bbb 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -5,6 +5,7 @@
     srcs: [
         "types.hal",
         "IDevice.hal",
+        "IEvent.hal",
         "IPreparedModel.hal",
     ],
 }
@@ -19,6 +20,7 @@
     out: [
         "android/hardware/neuralnetworks/1.0/types.cpp",
         "android/hardware/neuralnetworks/1.0/DeviceAll.cpp",
+        "android/hardware/neuralnetworks/1.0/EventAll.cpp",
         "android/hardware/neuralnetworks/1.0/PreparedModelAll.cpp",
     ],
 }
@@ -38,6 +40,11 @@
         "android/hardware/neuralnetworks/1.0/BnHwDevice.h",
         "android/hardware/neuralnetworks/1.0/BpHwDevice.h",
         "android/hardware/neuralnetworks/1.0/BsDevice.h",
+        "android/hardware/neuralnetworks/1.0/IEvent.h",
+        "android/hardware/neuralnetworks/1.0/IHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BnHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BpHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BsEvent.h",
         "android/hardware/neuralnetworks/1.0/IPreparedModel.h",
         "android/hardware/neuralnetworks/1.0/IHwPreparedModel.h",
         "android/hardware/neuralnetworks/1.0/BnHwPreparedModel.h",
diff --git a/neuralnetworks/1.0/IEvent.hal b/neuralnetworks/1.0/IEvent.hal
new file mode 100644
index 0000000..63afeaf
--- /dev/null
+++ b/neuralnetworks/1.0/IEvent.hal
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/* This HAL is a work in progress */
+
+package android.hardware.neuralnetworks@1.0;
+
+/**
+ * The IEvent interface is a callback object passed by the
+ * Neuralnetworks runtime to the vendor service. It is used as a
+ * synchronization primitive between one or more runtime threads and a
+ * single asynchronous vendor thread.  An event object is passed as an
+ * argument to a HIDL call that is expected to take a non-trivial
+ * amount of time. When the asynchronous execution thread has
+ * completed its computation, it must call "notify" on the event to
+ * indicate to the Neuralnetworks runtime whether the computation was
+ * successful or not, and that the corresponding output is ready to be
+ * consumed if the execution was successful.
+ *
+ * TODO: Mention that "notify" is also called by a runtime thread
+ * during CPU fallback execution? Depends on whether the HIDL comments
+ * are strictly for vendors or not.
+ */
+interface IEvent {
+
+    /**
+     * IEvent::notify is called by the server thread (i.e. the thread doing the
+     * work) to mark the event as completed so that any threads requiring the
+     * corresponding resources can continue executing.
+     *
+     * @param status Status of the execution associated with the Event.
+     *               Should be SUCCESS or ERROR.
+     */
+    oneway notify(Status status);
+
+};
diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal
index 566d6ac..428ddc7 100644
--- a/neuralnetworks/1.0/IPreparedModel.hal
+++ b/neuralnetworks/1.0/IPreparedModel.hal
@@ -18,8 +18,9 @@
 
 package android.hardware.neuralnetworks@1.0;
 
+import IEvent;
+
 interface IPreparedModel {
-    // TODO: The execution is synchronous.  Change that to have a callback on completion.
     // Multiple threads can call this execute function concurrently.
-    execute(Request request) generates(bool success);
+    execute(Request request, IEvent event) generates(bool success);
 };
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 959506a..844c44c 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -32,7 +32,8 @@
     UINT32                    = 7,
     TENSOR_FLOAT16            = 8,
     TENSOR_FLOAT32            = 9,
-    TENSOR_QUANT8_ASYMM       = 10,
+    TENSOR_INT32              = 10,
+    TENSOR_QUANT8_ASYMM       = 11,
 };
 
 // The type of operations.  Unlike the operation types found in
@@ -42,50 +43,60 @@
 // When modifying, be sure to update HAL_NUM_OPERATION_TYPES in HalIntefaces.h.
 enum OperationType : uint32_t {
     OEM_OPERATION                = 0,
-    AVERAGE_POOL                 = 1,
-    CONCATENATION                = 2,
-    CONV                         = 3,
-    DEPTHWISE_CONV               = 4,
-    MAX_POOL                     = 5,
-    L2_POOL                      = 6,
-    DEPTH_TO_SPACE               = 7,
-    SPACE_TO_DEPTH               = 8,
-    LOCAL_RESPONSE_NORMALIZATION = 9,
-    SOFTMAX                      = 10,
-    RESHAPE                      = 11,
-    SPLIT                        = 12,
-    FAKE_QUANT                   = 13,
-    ADD                          = 14,
-    FULLY_CONNECTED              = 15,
-    CAST                         = 16,
-    MUL                          = 17,
-    L2_NORMALIZATION             = 18,
-    LOGISTIC                     = 19,
-    RELU                         = 20,
-    RELU6                        = 21,
+    ADD                          = 1,
+    AVERAGE_POOL_2D              = 2,
+    CONCATENATION                = 3,
+    CONV_2D                      = 4,
+    DEPTHWISE_CONV_2D            = 5,
+    DEPTH_TO_SPACE               = 6,
+    DEQUANTIZE                   = 7,
+    EMBEDDING_LOOKUP             = 8,
+    FAKE_QUANT                   = 9,
+    FLOOR                        = 10,
+    FULLY_CONNECTED              = 11,
+    HASHTABLE_LOOKUP             = 12,
+    L2_NORMALIZATION             = 13,
+    L2_POOL_2D                   = 14,
+    LOCAL_RESPONSE_NORMALIZATION = 15,
+    LOGISTIC                     = 16,
+    LSH_PROJECTION               = 17,
+    LSTM                         = 18,
+    MAX_POOL_2D                  = 19,
+    MUL                          = 20,
+    RELU                         = 21,
     RELU1                        = 22,
-    TANH                         = 23,
-    DEQUANTIZE                   = 24,
-    FLOOR                        = 25,
-    GATHER                       = 26,
-    RESIZE_BILINEAR              = 27,
-    LSH_PROJECTION               = 28,
-    LSTM                         = 29,
-    SVDF                         = 30,
-    RNN                          = 31,
-    N_GRAM                       = 32,
-    EMBEDDING_LOOKUP             = 33,
-    HASHTABLE_LOOKUP             = 34,
+    RELU6                        = 23,
+    RESHAPE                      = 24,
+    RESIZE_BILINEAR              = 25,
+    RNN                          = 26,
+    SOFTMAX                      = 27,
+    SPACE_TO_DEPTH               = 28,
+    SVDF                         = 29,
+    TANH                         = 30,
 };
 
-// Two special values that can be used instead of a regular poolIndex.
-enum LocationValues : uint32_t {
-    // The location will be specified at runtime. It's either a temporary
-    // variable, an input, or an output.
-    LOCATION_AT_RUN_TIME = 0xFFFFFFFF,
-    // The operand's value is stored in the
-    // TODO: Only for old
-    LOCATION_SAME_BLOCK = 0xFFFFFFFE
+// Fused activation functions
+enum FusedActivationFunc : int32_t {
+    NONE  = 0,
+    RELU  = 1,
+    RELU1 = 2,
+    RELU6 = 3,
+};
+
+// How an operand is used.
+enum OperandLifeTime : uint32_t {
+    // The operand is internal to the model.  It's created by an operation
+    // and consumed by other operations.
+    TEMPORARY_VARIABLE,
+    // The operand is an input of the model. An operand can't be both
+    // input and output of a model.
+    MODEL_INPUT,
+    // The operand is an output of the model.
+    MODEL_OUTPUT,
+    // The operand is a constant found in Model.operandValues.
+    CONSTANT_COPY,
+    // The operand is a constant that was specified via a Memory object.
+    CONSTANT_REFERENCE
 };
 
 // Status of a device.
@@ -145,7 +156,20 @@
     float scale;
     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, or MODEL_OUTPUT:
+    // - All the fields will 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;
 };
 
@@ -161,12 +185,6 @@
     vec<uint32_t> outputs;
 };
 
-struct InputOutputInfo {
-    DataLocation location;
-    // If dimensions.size() > 0, we have updated dimensions.
-    vec<uint32_t> dimensions;
-};
-
 struct Model {
     vec<Operand> operands;
     vec<Operation> operations;
@@ -176,8 +194,23 @@
     vec<memory> pools;
 };
 
+struct RequestArgument {
+    // The location within one of the memory pools
+    DataLocation location;
+    // If dimensions.size() > 0, dimension information was provided along with the
+    // argument.  This can be the case for models that accept inputs of varying size.
+    // This can't change the rank, just the value of the dimensions that were
+    // unspecified in the model.
+    vec<uint32_t> dimensions;
+};
+
 struct Request {
-    vec<InputOutputInfo> inputs;
-    vec<InputOutputInfo> outputs;
+    vec<RequestArgument> inputs;
+    vec<RequestArgument> outputs;
     vec<memory> pools;
 };
+
+enum Status : uint32_t {
+    SUCCESS,
+    ERROR,
+};
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index d76b2c3..1efff0e 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -16,7 +16,10 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
-    srcs: ["VtsHalNeuralnetworksV1_0TargetTest.cpp"],
+    srcs: [
+        "Event.cpp",
+        "VtsHalNeuralnetworksV1_0TargetTest.cpp",
+    ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
diff --git a/neuralnetworks/1.0/vts/functional/Event.cpp b/neuralnetworks/1.0/vts/functional/Event.cpp
new file mode 100644
index 0000000..0fab86b
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Event.cpp
@@ -0,0 +1,76 @@
+#include "Event.h"
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace implementation {
+
+Event::Event() : mStatus(Status::WAITING) {}
+
+Event::~Event() {
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+Return<void> Event::notify(ReturnedStatus status) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStatus = status == ReturnedStatus::SUCCESS ? Status::SUCCESS : Status::ERROR;
+        if (mStatus == Status::SUCCESS && mCallback != nullptr) {
+            bool success = mCallback();
+            if (!success) {
+                LOG(ERROR) << "Event::notify -- callback failed";
+            }
+        }
+    }
+    mCondition.notify_all();
+    return Void();
+}
+
+Event::Status Event::poll() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mStatus;
+}
+
+Event::Status Event::wait() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this]{return mStatus != Status::WAITING;});
+    return mStatus;
+}
+
+bool Event::on_finish(std::function<bool(void)> callback) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mCallback != nullptr) {
+        LOG(ERROR) << "Event::on_finish -- a callback has already been bound to this event";
+        return false;
+    }
+    if (callback == nullptr) {
+        LOG(ERROR) << "Event::on_finish -- the new callback is invalid";
+        return false;
+    }
+    mCallback = std::move(callback);
+    return true;
+}
+
+bool Event::bind_thread(std::thread&& asyncThread) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mThread.joinable()) {
+        LOG(ERROR) << "Event::bind_thread -- a thread has already been bound to this event";
+        return false;
+    }
+    if (!asyncThread.joinable()) {
+        LOG(ERROR) << "Event::bind_thread -- the new thread is not joinable";
+        return false;
+    }
+    mThread = std::move(asyncThread);
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Event.h b/neuralnetworks/1.0/vts/functional/Event.h
new file mode 100644
index 0000000..2e19585
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Event.h
@@ -0,0 +1,192 @@
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
+
+#include <android/hardware/neuralnetworks/1.0/IEvent.h>
+#include <chrono>
+#include <condition_variable>
+#include <functional>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+using ReturnedStatus = ::android::hardware::neuralnetworks::V1_0::Status;
+
+/**
+ * The Event class is used internally by the Neuralnetworks runtime to
+ * synchronize between different threads. An asynchronous task is launched
+ * paired with an event object. When a client thread requires the output being
+ * processed by the asynchronous task, the client thread can wait for the result
+ * and be blocked until it has completed or a timeout condition has been
+ * reached, or poll the result periodically. Both poll and wait* may safely be
+ * called concurrently, even on the same event. When the server thread has
+ * completed, it should immediately call "notify" to indicate the corresponding
+ * output has been produced and awaken any client threads waiting on the event.
+ *
+ * This class exists to enable synchronization across HIDL. When synchronization
+ * is only required in the same process, consider using std::future, std::mutex,
+ * std::condition_variable, or std::experimental::latch instead.
+ */
+struct Event : public IEvent {
+    Event();
+    ~Event() override;
+
+    /**
+     * Event::Status::WAITING -- The corresponding asynchronous execution has
+     *                           not yet finished.
+     * Event::Status::SUCCESS -- The corresponding asynchronous execution has
+     *                           succeeded and the output is ready to be
+     *                           consumed.
+     * Event::Status::TIMEOUT -- The calling thread has waited longer than the
+     *                           user has specified. This only applies to the
+     *                           methods Event::wait_for and Event::wait_until.
+     * Event::Status::ERROR   -- The corresponding asynchronous execution has
+     *                           failed to properly execute.
+     */
+    enum class Status : uint32_t {
+        WAITING,
+        SUCCESS,
+        TIMEOUT,
+        ERROR,
+    };
+
+    /**
+     * IEvent::notify marks the event with the return status of the
+     * asynchronous call the event is paired with and enables all
+     * prior and future wait calls on the Event object to proceed. The
+     * call to IEvent::notify happens before any wait* calls on
+     * this event return (except in the case of TIMEOUT) and before
+     * any poll calls that see the resulting status. The asynchronous
+     * call the event is paired with must ensure that any update to
+     * state that should be visible to the caller of wait* or poll
+     * happens before the call to IEvent::notify.
+     *
+     * IEvent::notify can be called at most once on a given event.
+     *
+     * @param neuralnetworks::V1_0::Status SUCCESS or ERROR
+     */
+    Return<void> notify(ReturnedStatus status) override;
+
+    /**
+     * Event::poll returns the current status of the event.
+     *
+     * @return Status SUCCESS, ERROR, or WAITING
+     */
+    Event::Status poll();
+
+    /**
+     * Event::wait blocks until the event has been signaled.
+     *
+     * @return Status SUCCESS or ERROR
+     */
+    Event::Status wait();
+
+    /**
+     * Event::wait_for blocks until the event has been signaled or the time
+     * duration from the time the wait_for function was called has expired,
+     * whichever comes first.
+     *
+     * @return Status SUCCESS, ERROR, or TIMEOUT
+     */
+    template<class Rep, class Period>
+    Event::Status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
+
+    /**
+     * Event::wait_until blocks until the event has been signaled or a certain
+     * time has been reached, whichever comes first.
+     *
+     * @return Status SUCCESS, ERROR, or TIMEOUT
+     */
+    template<class Clock, class Duration>
+    Event::Status wait_until(const std::chrono::time_point<Clock,Duration>& timeout_duration);
+
+    /**
+     * Event::on_finish binds a callback function to the event. The
+     * callback will be executed when IEvent::notify is called, before
+     * any calls to wait* return. (Note that wait_for or wait_until
+     * can return TIMEOUT before IEvent::notify is called for the
+     * first time, and hence before the callback is executed.)
+     *
+     * The callback function must not synchronize with or otherwise
+     * access the event object it is bound to.
+     *
+     * Event::on_finish can be called at most once on a given event.
+     *
+     * @param callback Function to be invoked the first time IEvent::notify is
+     *                 called. Must have a target -- i.e., must not compare equal
+     *                 to nullptr. Callback returns true if it successfully
+     *                 completes, false if it fails.
+     * @return bool True if the callback was successfully bound, false if
+     *              unsuccessful.
+     *
+     * TODO: What if notify has already been called before on_finish?
+     * TODO: Why does the return value of the callback matter?
+     */
+     bool on_finish(std::function<bool(void)> callback);
+
+    /**
+     * Event::bind_thread binds a thread to the event ensuring that the thread
+     * has fully finished and cleaned its resources before the event is
+     * destroyed. The thread should be bound using std::move.
+     *
+     * The bound thread shall not call any Event method with the exception of
+     * IEvent::notify, which it will call when the thread has finished its
+     * computation.
+     *
+     * Event::bind_thread can be called at most once on a given event.
+     *
+     * @param asyncThread Thread to be bound to the event. The thread object
+     *                    must represent a thread of execution -- i.e.,
+     *                    asyncThread.joinable() must be true.
+     * @return bool True if successful, false if thread was not properly bound.
+     */
+     bool bind_thread(std::thread&& asyncThread);
+
+ private:
+    Status                    mStatus;
+    std::mutex                mMutex;
+    std::condition_variable   mCondition;
+    std::function<bool(void)> mCallback;
+    std::thread               mThread;
+};
+
+
+// template function implementations
+
+template<class Rep, class Period>
+Event::Status Event::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    std::cv_status status = mCondition.wait_for(lock, timeout_duration,
+                                                [this]{return mStatus != Status::WAITING;});
+    return status != std::cv_status::timeout ? mStatus : Status::TIMEOUT;
+}
+
+template<class Clock, class Duration>
+Event::Status Event::wait_until(const std::chrono::time_point<Clock,Duration>& timeout_time) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    std::cv_status status = mCondition.wait_until(lock, timeout_time,
+                                                  [this]{return mStatus != Status::WAITING;});
+    return status != std::cv_status::timeout ? mStatus : Status::TIMEOUT;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
index 84e67cb..90ccd06 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "Event.h"
 #include "VtsHalNeuralnetworksV1_0TargetTest.h"
 #include <android-base/logging.h>
 #include <android/hidl/memory/1.0/IMemory.h>
@@ -29,9 +30,13 @@
 namespace vts {
 namespace functional {
 
+using ::android::hardware::neuralnetworks::V1_0::implementation::Event;
+
 // A class for test environment setup
 NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
 
+NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
+
 NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
     // This has to return a "new" object because it is freed inside
     // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
@@ -44,6 +49,8 @@
 }
 
 // The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
+
 void NeuralnetworksHidlTest::SetUp() {
     device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
         NeuralnetworksHidlEnvironment::getInstance());
@@ -96,7 +103,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_AT_RUN_TIME),
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = 0},
         },
@@ -106,7 +114,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_SAME_BLOCK),
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = size},
         },
@@ -116,7 +125,8 @@
             .numberOfConsumers = 1,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_SAME_BLOCK),
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0,
                          .offset = size,
                          .length = sizeof(int32_t)},
         },
@@ -126,7 +136,8 @@
             .numberOfConsumers = 0,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .location = {.poolIndex = static_cast<uint32_t>(LocationValues::LOCATION_AT_RUN_TIME),
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0,
                          .offset = 0,
                          .length = 0},
         },
@@ -143,7 +154,7 @@
     std::vector<uint8_t> operandValues(
         reinterpret_cast<const uint8_t*>(operand2Data.data()),
         reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
-    int32_t activation[1] = {0};
+    int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
     operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
                          reinterpret_cast<const uint8_t*>(&activation[1]));
 
@@ -206,10 +217,10 @@
     // prepare inputs
     uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
     uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
-    std::vector<InputOutputInfo> inputs = {{
+    std::vector<RequestArgument> inputs = {{
         .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
     }};
-    std::vector<InputOutputInfo> outputs = {{
+    std::vector<RequestArgument> outputs = {{
         .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
     }};
     std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
@@ -226,21 +237,32 @@
     float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
     ASSERT_NE(nullptr, inputPtr);
     ASSERT_NE(nullptr, outputPtr);
+    inputMemory->update();
+    outputMemory->update();
     std::copy(inputData.begin(), inputData.end(), inputPtr);
     std::copy(outputData.begin(), outputData.end(), outputPtr);
     inputMemory->commit();
     outputMemory->commit();
 
     // execute request
-    bool success = preparedModel->execute({.inputs = inputs, .outputs = outputs, .pools = pools});
+    sp<Event> event = sp<Event>(new Event());
+    ASSERT_NE(nullptr, event.get());
+    bool success = preparedModel->execute({.inputs = inputs, .outputs = outputs, .pools = pools},
+                                          event);
     EXPECT_TRUE(success);
+    Event::Status status = event->wait();
+    EXPECT_EQ(Event::Status::SUCCESS, status);
 
     // validate results { 1+5, 2+6, 3+7, 4+8 }
-    outputMemory->update();
+    outputMemory->read();
     std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
+    outputMemory->commit();
     EXPECT_EQ(expectedData, outputData);
 }
 
+// TODO: Add tests for execution failure, or wait_for/wait_until timeout.
+//       Discussion: https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222
+
 }  // namespace functional
 }  // namespace vts
 }  // namespace V1_0
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
index bb0cdaa..9c56e6a 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
@@ -31,6 +31,7 @@
 using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
 using ::android::hardware::neuralnetworks::V1_0::Capabilities;
 using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
 using ::android::hardware::neuralnetworks::V1_0::Model;
 using ::android::hardware::neuralnetworks::V1_0::OperationType;
 using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
@@ -59,15 +60,17 @@
     NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
 
    public:
+    ~NeuralnetworksHidlEnvironment() override;
     static NeuralnetworksHidlEnvironment* getInstance();
-    virtual void registerTestServices() override;
+    void registerTestServices() override;
 };
 
 // The main test class for NEURALNETWORKS HIDL HAL.
 class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
-    virtual void SetUp() override;
-    virtual void TearDown() override;
+    ~NeuralnetworksHidlTest() override;
+    void SetUp() override;
+    void TearDown() override;
 
     sp<IDevice> device;
 };
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index d93b176..795af86 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -70,7 +70,7 @@
 TEST_F(RadioHidlTest, setRadioPower) {
     int serial = GetRandomSerialNumber();
 
-    radio->setRadioPower(serial, 0);
+    radio->setRadioPower(serial, 1);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
diff --git a/tests/bar/1.0/.hidl_for_test b/tests/bar/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/bar/1.0/.hidl_for_test
diff --git a/tests/bar/1.0/Android.bp b/tests/bar/1.0/Android.bp
index 2dbfb0f..44ae7a5 100644
--- a/tests/bar/1.0/Android.bp
+++ b/tests/bar/1.0/Android.bp
@@ -67,7 +67,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.bar@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.bar@1.0_genc++"],
diff --git a/tests/baz/1.0/.hidl_for_test b/tests/baz/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/baz/1.0/.hidl_for_test
diff --git a/tests/baz/1.0/Android.bp b/tests/baz/1.0/Android.bp
index cec3039..7fa8b27 100644
--- a/tests/baz/1.0/Android.bp
+++ b/tests/baz/1.0/Android.bp
@@ -60,7 +60,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.baz@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.baz@1.0_genc++"],
diff --git a/tests/expression/1.0/.hidl_for_test b/tests/expression/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/expression/1.0/.hidl_for_test
diff --git a/tests/expression/1.0/Android.bp b/tests/expression/1.0/Android.bp
index 093b660..0ea0acf 100644
--- a/tests/expression/1.0/Android.bp
+++ b/tests/expression/1.0/Android.bp
@@ -42,7 +42,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.expression@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.expression@1.0_genc++"],
diff --git a/tests/extension/light/2.0/.hidl_for_test b/tests/extension/light/2.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/extension/light/2.0/.hidl_for_test
diff --git a/tests/extension/light/2.0/Android.bp b/tests/extension/light/2.0/Android.bp
index 52117b4..e8a5017 100644
--- a/tests/extension/light/2.0/Android.bp
+++ b/tests/extension/light/2.0/Android.bp
@@ -39,7 +39,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.extension.light@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.extension.light@2.0_genc++"],
diff --git a/tests/foo/1.0/.hidl_for_test b/tests/foo/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/foo/1.0/.hidl_for_test
diff --git a/tests/foo/1.0/Android.bp b/tests/foo/1.0/Android.bp
index d0038ab..b5de12e 100644
--- a/tests/foo/1.0/Android.bp
+++ b/tests/foo/1.0/Android.bp
@@ -67,7 +67,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.foo@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.foo@1.0_genc++"],
diff --git a/tests/hash/1.0/.hidl_for_test b/tests/hash/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/hash/1.0/.hidl_for_test
diff --git a/tests/hash/1.0/Android.bp b/tests/hash/1.0/Android.bp
index 336963e..d4d1d1a 100644
--- a/tests/hash/1.0/Android.bp
+++ b/tests/hash/1.0/Android.bp
@@ -35,7 +35,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.hash@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.hash@1.0_genc++"],
diff --git a/tests/inheritance/1.0/.hidl_for_test b/tests/inheritance/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/inheritance/1.0/.hidl_for_test
diff --git a/tests/inheritance/1.0/Android.bp b/tests/inheritance/1.0/Android.bp
index a8c0e6c..93a8ad5 100644
--- a/tests/inheritance/1.0/Android.bp
+++ b/tests/inheritance/1.0/Android.bp
@@ -56,7 +56,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.inheritance@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.inheritance@1.0_genc++"],
diff --git a/tests/libhwbinder/1.0/.hidl_for_test b/tests/libhwbinder/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libhwbinder/1.0/.hidl_for_test
diff --git a/tests/libhwbinder/1.0/Android.bp b/tests/libhwbinder/1.0/Android.bp
index 6132628..4f3beb0 100644
--- a/tests/libhwbinder/1.0/Android.bp
+++ b/tests/libhwbinder/1.0/Android.bp
@@ -42,7 +42,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.libhwbinder@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.libhwbinder@1.0_genc++"],
diff --git a/tests/libhwbinder/aidl/.hidl_for_test b/tests/libhwbinder/aidl/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libhwbinder/aidl/.hidl_for_test
diff --git a/tests/memory/1.0/.hidl_for_test b/tests/memory/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/memory/1.0/.hidl_for_test
diff --git a/tests/memory/1.0/Android.bp b/tests/memory/1.0/Android.bp
index c5cc4a0..d39ba28 100644
--- a/tests/memory/1.0/Android.bp
+++ b/tests/memory/1.0/Android.bp
@@ -35,7 +35,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.memory@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.memory@1.0_genc++"],
diff --git a/tests/msgq/1.0/.hidl_for_test b/tests/msgq/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/msgq/1.0/.hidl_for_test
diff --git a/tests/msgq/1.0/Android.bp b/tests/msgq/1.0/Android.bp
index 017e0d4..7758ee8 100644
--- a/tests/msgq/1.0/Android.bp
+++ b/tests/msgq/1.0/Android.bp
@@ -42,7 +42,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.msgq@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.msgq@1.0_genc++"],
diff --git a/tests/multithread/1.0/.hidl_for_test b/tests/multithread/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/multithread/1.0/.hidl_for_test
diff --git a/tests/multithread/1.0/Android.bp b/tests/multithread/1.0/Android.bp
index 68c19aa..76ad2c1 100644
--- a/tests/multithread/1.0/Android.bp
+++ b/tests/multithread/1.0/Android.bp
@@ -35,7 +35,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.multithread@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.multithread@1.0_genc++"],
diff --git a/tests/pointer/1.0/.hidl_for_test b/tests/pointer/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/pointer/1.0/.hidl_for_test
diff --git a/tests/pointer/1.0/Android.bp b/tests/pointer/1.0/Android.bp
index 55598ca..178f165 100644
--- a/tests/pointer/1.0/Android.bp
+++ b/tests/pointer/1.0/Android.bp
@@ -42,7 +42,7 @@
     ],
 }
 
-cc_library {
+cc_test_library {
     name: "android.hardware.tests.pointer@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.pointer@1.0_genc++"],
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
index 833f219..0985d94 100644
--- a/thermal/1.1/Android.bp
+++ b/thermal/1.1/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.thermal@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.thermal@1.1_genc++"],
     generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
index cea5bf8..f5f01fa 100644
--- a/thermal/1.1/vts/functional/Android.bp
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -16,20 +16,11 @@
 
 cc_test {
     name: "VtsHalThermalV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalThermalV1_1TargetTest.cpp"],
-    shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
+    static_libs: [
         "android.hardware.thermal@1.0",
         "android.hardware.thermal@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h
index 2f95c23..f36c8bd 100644
--- a/wifi/1.1/default/hidl_return_util.h
+++ b/wifi/1.1/default/hidl_return_util.h
@@ -55,6 +55,25 @@
   return Void();
 }
 
+// Use for HIDL methods which return only an instance of WifiStatus.
+// This version passes the global lock acquired to the body of the method.
+// Note: Only used by IWifi::stop() currently.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCallWithLock(
+    ObjT* obj,
+    WifiStatusCode status_code_if_invalid,
+    WorkFuncT&& work,
+    const std::function<void(const WifiStatus&)>& hidl_cb,
+    Args&&... args) {
+  auto lock = hidl_sync_util::acquireGlobalLock();
+  if (obj->isValid()) {
+    hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
+  } else {
+    hidl_cb(createWifiStatus(status_code_if_invalid));
+  }
+  return Void();
+}
+
 // Use for HIDL methods which return instance of WifiStatus and a single return
 // value.
 template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
index 8456b90..c46ef95 100644
--- a/wifi/1.1/default/wifi.cpp
+++ b/wifi/1.1/default/wifi.cpp
@@ -31,6 +31,7 @@
 namespace V1_1 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
 
 Wifi::Wifi()
     : legacy_hal_(new legacy_hal::WifiLegacyHal()),
@@ -64,8 +65,8 @@
 }
 
 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-  return validateAndCall(
-      this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
+  return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
+                                 &Wifi::stopInternal, hidl_status_cb);
 }
 
 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
@@ -120,7 +121,8 @@
   return wifi_status;
 }
 
-WifiStatus Wifi::stopInternal() {
+WifiStatus Wifi::stopInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   if (run_state_ == RunState::STOPPED) {
     return createWifiStatus(WifiStatusCode::SUCCESS);
   } else if (run_state_ == RunState::STOPPING) {
@@ -133,7 +135,7 @@
     chip_->invalidate();
     chip_.clear();
   }
-  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
+  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
   if (wifi_status.code == WifiStatusCode::SUCCESS) {
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
       if (!callback->onStop().isOk()) {
@@ -180,11 +182,11 @@
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
   legacy_hal::wifi_error legacy_status =
-      legacy_hal_->stop(on_complete_callback_);
+      legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; });
   if (legacy_status != legacy_hal::WIFI_SUCCESS) {
     LOG(ERROR) << "Failed to stop legacy HAL: "
                << legacyErrorToString(legacy_status);
diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h
index 1ade2d8..3a64cbd 100644
--- a/wifi/1.1/default/wifi.h
+++ b/wifi/1.1/default/wifi.h
@@ -61,12 +61,13 @@
   WifiStatus registerEventCallbackInternal(
       const sp<IWifiEventCallback>& event_callback);
   WifiStatus startInternal();
-  WifiStatus stopInternal();
+  WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
   std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
   std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
 
   WifiStatus initializeLegacyHal();
-  WifiStatus stopLegacyHalAndDeinitializeModeController();
+  WifiStatus stopLegacyHalAndDeinitializeModeController(
+      std::unique_lock<std::recursive_mutex>* lock);
 
   // Instance is created in this root level |IWifi| HIDL interface object
   // and shared with all the child HIDL interface objects.
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
index 151a600..a6f6971 100644
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ b/wifi/1.1/default/wifi_legacy_hal.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <array>
+#include <chrono>
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
@@ -34,6 +35,7 @@
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 50;
 
 // Helper function to create a non-const char* for legacy Hal API's.
 std::vector<char> makeCharVec(const std::string& str) {
@@ -53,7 +55,8 @@
 // Legacy HAL functions accept "C" style function pointers, so use global
 // functions to pass to the legacy HAL function and store the corresponding
 // std::function methods to be invoked.
-// Callback to be invoked once |stop| is complete.
+//
+// Callback to be invoked once |stop| is complete
 std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
 void onAsyncStopComplete(wifi_handle handle) {
   const auto lock = hidl_sync_util::acquireGlobalLock();
@@ -369,6 +372,7 @@
 }
 
 wifi_error WifiLegacyHal::stop(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     const std::function<void()>& on_stop_complete_user_callback) {
   if (!is_started_) {
     LOG(DEBUG) << "Legacy HAL already stopped";
@@ -376,19 +380,27 @@
     return WIFI_SUCCESS;
   }
   LOG(DEBUG) << "Stopping legacy HAL";
-  on_stop_complete_internal_callback = [on_stop_complete_user_callback,
-                                        this](wifi_handle handle) {
+  on_stop_complete_internal_callback =
+      [on_stop_complete_user_callback, this](wifi_handle handle) {
     CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+    LOG(INFO) << "Legacy HAL stop complete callback received";
     // Invalidate all the internal pointers now that the HAL is
     // stopped.
     invalidate();
     iface_tool_.SetWifiUpState(false);
     on_stop_complete_user_callback();
+    is_started_ = false;
   };
   awaiting_event_loop_termination_ = true;
   global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+  const auto status = stop_wait_cv_.wait_for(
+      *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+      [this] { return !awaiting_event_loop_termination_; });
+  if (!status) {
+    LOG(ERROR) << "Legacy HAL stop failed or timed out";
+    return WIFI_ERROR_UNKNOWN;
+  }
   LOG(DEBUG) << "Legacy HAL stop complete";
-  is_started_ = false;
   return WIFI_SUCCESS;
 }
 
@@ -1257,11 +1269,13 @@
 void WifiLegacyHal::runEventLoop() {
   LOG(DEBUG) << "Starting legacy HAL event loop";
   global_func_table_.wifi_event_loop(global_handle_);
+  const auto lock = hidl_sync_util::acquireGlobalLock();
   if (!awaiting_event_loop_termination_) {
     LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
   }
   LOG(DEBUG) << "Legacy HAL event loop terminated";
   awaiting_event_loop_termination_ = false;
+  stop_wait_cv_.notify_one();
 }
 
 std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h
index caa1bd5..5498803 100644
--- a/wifi/1.1/default/wifi_legacy_hal.h
+++ b/wifi/1.1/default/wifi_legacy_hal.h
@@ -20,6 +20,7 @@
 #include <functional>
 #include <thread>
 #include <vector>
+#include <condition_variable>
 
 #include <wifi_system/interface_tool.h>
 
@@ -149,8 +150,10 @@
   wifi_error initialize();
   // Start the legacy HAL and the event looper thread.
   wifi_error start();
-  // Deinitialize the legacy HAL and stop the event looper thread.
-  wifi_error stop(const std::function<void()>& on_complete_callback);
+  // Deinitialize the legacy HAL and wait for the event loop thread to exit
+  // using a predefined timeout.
+  wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
+                  const std::function<void()>& on_complete_callback);
   // Wrappers for all the functions in the legacy HAL function table.
   std::pair<wifi_error, std::string> getDriverVersion();
   std::pair<wifi_error, std::string> getFirmwareVersion();
@@ -293,6 +296,7 @@
   wifi_interface_handle wlan_interface_handle_;
   // Flag to indicate if we have initiated the cleanup of legacy HAL.
   std::atomic<bool> awaiting_event_loop_termination_;
+  std::condition_variable_any stop_wait_cv_;
   // Flag to indicate if the legacy HAL has been started.
   bool is_started_;
   wifi_system::InterfaceTool iface_tool_;