Merge "wifi: Fix for VtsHalWifiSupplicantV1_0TargetTest failures"
diff --git a/audio/6.0/IDevice.hal b/audio/6.0/IDevice.hal
index c2e310c..2026d8f 100644
--- a/audio/6.0/IDevice.hal
+++ b/audio/6.0/IDevice.hal
@@ -149,7 +149,10 @@
                     AudioConfig suggestedConfig);
 
     /**
-     * Returns whether HAL supports audio patches.
+     * Returns whether HAL supports audio patches. Patch represents a connection
+     * between signal source(s) and signal sink(s). If HAL doesn't support
+     * patches natively (in hardware) then audio system will need to establish
+     * them in software.
      *
      * @return supports true if audio patches are supported.
      */
@@ -316,7 +319,9 @@
     close() generates (Result retval);
 
     /**
-     * Applies an audio effect to an audio device.
+     * Applies an audio effect to an audio device. The effect is inserted
+     * according to its insertion preference specified by INSERT_... EffectFlags
+     * in the EffectDescriptor.
      *
      * @param device identifies the sink or source device this effect must be applied to.
      *               "device" is the AudioPortHandle indicated for the device when the audio
diff --git a/audio/common/6.0/types.hal b/audio/common/6.0/types.hal
index 26e8acb..b2806c7 100644
--- a/audio/common/6.0/types.hal
+++ b/audio/common/6.0/types.hal
@@ -91,37 +91,76 @@
 enum AudioStreamType : int32_t {
     // These values must kept in sync with
     //  frameworks/base/media/java/android/media/AudioSystem.java
+    /** Used to identify the default audio stream volume. */
     DEFAULT          = -1,
+    /** Specifies the minimum value for use in checks and loops. */
     MIN              = 0,
+    /** Used to identify the volume of audio streams for phone calls. */
     VOICE_CALL       = 0,
+    /** Used to identify the volume of audio streams for system sounds. */
     SYSTEM           = 1,
+    /**
+     * Used to identify the volume of audio streams for the phone ring
+     * and message alerts.
+     */
     RING             = 2,
+    /** Used to identify the volume of audio streams for music playback. */
     MUSIC            = 3,
+    /** Used to identify the volume of audio streams for alarms. */
     ALARM            = 4,
+    /** Used to identify the volume of audio streams for notifications. */
     NOTIFICATION     = 5,
+    /**
+     * Used to identify the volume of audio streams for phone calls
+     * when connected on bluetooth.
+     */
     BLUETOOTH_SCO    = 6,
-    ENFORCED_AUDIBLE = 7,  // Sounds that cannot be muted by user and must be
-                           // routed to speaker
+    /**
+     * Used to identify the volume of audio streams for enforced system
+     * sounds in certain countries (e.g camera in Japan). */
+    ENFORCED_AUDIBLE = 7,
+    /** Used to identify the volume of audio streams for DTMF tones. */
     DTMF             = 8,
-    TTS              = 9,  // Transmitted Through Speaker.  Plays over speaker
-                           // only, silent on other devices
-    ACCESSIBILITY    = 10, // For accessibility talk back prompts
-    ASSISTANT        = 11, // For virtual assistant service
+    /**
+     * Used to identify the volume of audio streams exclusively transmitted
+     * through the speaker (TTS) of the device.
+     */
+    TTS              = 9,
+    /**
+     * Used to identify the volume of audio streams for accessibility prompts.
+     */
+    ACCESSIBILITY    = 10,
+    /** Used to identify the volume of audio streams for virtual assistant. */
+    ASSISTANT        = 11,
 };
 
 @export(name="audio_source_t", value_prefix="AUDIO_SOURCE_")
 enum AudioSource : int32_t {
     // These values must kept in sync with
     //  frameworks/base/media/java/android/media/MediaRecorder.java,
-    //  frameworks/av/services/audiopolicy/AudioPolicyService.cpp,
     //  system/media/audio_effects/include/audio_effects/audio_effects_conf.h
+    /** Default audio source. */
     DEFAULT             = 0,
+    /** Microphone audio source. */
     MIC                 = 1,
+    /** Voice call uplink (Tx) audio source. */
     VOICE_UPLINK        = 2,
+    /** Voice call downlink (Rx) audio source. */
     VOICE_DOWNLINK      = 3,
+    /** Voice call uplink + downlink audio source. */
     VOICE_CALL          = 4,
+    /**
+     * Microphone audio source tuned for video recording, with the same
+     * orientation as the camera if available.
+     */
     CAMCORDER           = 5,
+    /** Microphone audio source tuned for voice recognition. */
     VOICE_RECOGNITION   = 6,
+    /**
+     * Microphone audio source tuned for voice communications such as VoIP. It
+     * will for instance take advantage of echo cancellation or automatic gain
+     * control if available.
+     */
     VOICE_COMMUNICATION = 7,
     /**
      * Source for the mix to be presented remotely. An example of remote
@@ -146,7 +185,9 @@
      * to include all post processing applied to the playback path.
      */
     ECHO_REFERENCE      = 1997,
+    /** Virtual source for the built-in FM tuner. */
     FM_TUNER            = 1998,
+    /** Virtual source for the last captured hotword. */
     HOTWORD             = 1999,
 };
 
@@ -562,7 +603,7 @@
     IN_CALL          = 2,
     /** Calls handled by apps (Eg: Hangout). */
     IN_COMMUNICATION = 3,
-    /** Call screening in progress */
+    /** Call screening in progress. */
     CALL_SCREEN      = 4,
 };
 
@@ -748,23 +789,85 @@
     // These values must kept in sync with
     //  frameworks/base/media/java/android/media/AudioAttributes.java
     // Note that not all framework values are exposed
+    /**
+     * Usage value to use when the usage is unknown.
+     */
     UNKNOWN                            = 0,
+    /**
+     * Usage value to use when the usage is media, such as music, or movie
+     * soundtracks.
+     */
     MEDIA                              = 1,
+    /**
+     * Usage value to use when the usage is voice communications, such as
+     * telephony or VoIP.
+     */
     VOICE_COMMUNICATION                = 2,
+    /**
+     * Usage value to use when the usage is in-call signalling, such as with
+     * a "busy" beep, or DTMF tones.
+     */
     VOICE_COMMUNICATION_SIGNALLING     = 3,
+    /**
+     * Usage value to use when the usage is an alarm (e.g. wake-up alarm).
+     */
     ALARM                              = 4,
+    /**
+     * Usage value to use when the usage is a generic notification.
+     */
     NOTIFICATION                       = 5,
+    /**
+     * Usage value to use when the usage is telephony ringtone.
+     */
     NOTIFICATION_TELEPHONY_RINGTONE    = 6,
+    /**
+     * Usage value to use when the usage is for accessibility, such as with
+     * a screen reader.
+     */
     ASSISTANCE_ACCESSIBILITY           = 11,
+    /**
+     * Usage value to use when the usage is driving or navigation directions.
+     */
     ASSISTANCE_NAVIGATION_GUIDANCE     = 12,
+    /**
+     * Usage value to use when the usage is sonification, such as  with user
+     * interface sounds.
+     */
     ASSISTANCE_SONIFICATION            = 13,
+    /**
+     * Usage value to use when the usage is for game audio.
+     */
     GAME                               = 14,
+    /**
+     * Usage value to use when feeding audio to the platform and replacing
+     * "traditional" audio source, such as audio capture devices.
+     */
     VIRTUAL_SOURCE                     = 15,
+    /**
+     * Usage value to use for audio responses to user queries, audio
+     * instructions or help utterances.
+     */
     ASSISTANT                          = 16,
+    /**
+     * Usage value to use for assistant voice interaction with remote caller
+     * on Cell and VoIP calls.
+     */
     CALL_ASSISTANT                     = 17,
+    /**
+     * Usage value to use when the usage is an emergency.
+     */
     EMERGENCY                          = 1000,
+    /**
+     * Usage value to use when the usage is a safety sound.
+     */
     SAFETY                             = 1001,
+    /**
+     * Usage value to use when the usage is a vehicle status.
+     */
     VEHICLE_STATUS                     = 1002,
+    /**
+     * Usage value to use when the usage is an announcement.
+     */
     ANNOUNCEMENT                       = 1003,
 };
 
@@ -773,10 +876,30 @@
 enum AudioContentType : uint32_t {
     // Do not change these values without updating their counterparts
     // in frameworks/base/media/java/android/media/AudioAttributes.java
+    /**
+     * Content type value to use when the content type is unknown, or other than
+     * the ones defined.
+     */
     UNKNOWN      = 0,
+    /**
+     * Content type value to use when the content type is speech.
+     */
     SPEECH       = 1,
+    /**
+     * Content type value to use when the content type is music.
+     */
     MUSIC        = 2,
+    /**
+     * Content type value to use when the content type is a soundtrack,
+     * typically accompanying a movie or TV program.
+     */
     MOVIE        = 3,
+    /**
+     * Content type value to use when the content type is a sound used to
+     * accompany a user action, such as a beep or sound effect expressing a key
+     * click, or event, such as the type of a sound for a bonus being received
+     * in a game. These sounds are mostly synthesized or short Foley sounds.
+     */
     SONIFICATION = 4,
 };
 
diff --git a/audio/common/all-versions/copyHAL.sh b/audio/common/all-versions/copyHAL.sh
index 56559d1..0a32a51 100755
--- a/audio/common/all-versions/copyHAL.sh
+++ b/audio/common/all-versions/copyHAL.sh
@@ -21,7 +21,7 @@
 
 readonly FWK_DIRECTORY=frameworks/av/media/libaudiohal
 readonly IMPL_DIRECTORY=impl
-readonly IMPL_FACTORYHAL=$IMPL_DIRECTORY/include/libaudiohal/FactoryHalHidl.h
+readonly IMPL_FACTORYHAL=FactoryHalHidl.cpp
 
 readonly VTS_DIRECTORY=test/vts-testcase/hal/audio
 readonly VTS_LIST=test/vts/tools/build/tasks/list/vts_test_lib_hidl_package_list.mk
@@ -150,7 +150,7 @@
 
 createFrameworkAdapter() {
     updateVersion -v original_before=1 Android.bp
-    updateVersion -v original_before=1 -v RS= -v ORS='\n\n' $IMPL_FACTORYHAL/Android.bp
+    updateVersion -v original_before=1 -v RS= -v ORS='\n\n' $IMPL_DIRECTORY/Android.bp
     updateVersion -v original_after=1 $IMPL_FACTORYHAL
 }
 echo "Now creating the framework adapter version"
diff --git a/audio/effect/6.0/xml/api/current.txt b/audio/effect/6.0/xml/api/current.txt
index 072cf8f..cd5ca2a 100644
--- a/audio/effect/6.0/xml/api/current.txt
+++ b/audio/effect/6.0/xml/api/current.txt
@@ -34,6 +34,10 @@
 
   public class DeviceProcessType extends audio.effects.V6_0.StreamProcessingType {
     ctor public DeviceProcessType();
+    method public String getAddress();
+    method public audio.effects.V6_0.DeviceType getType();
+    method public void setAddress(String);
+    method public void setType(audio.effects.V6_0.DeviceType);
   }
 
   public enum DeviceType {
diff --git a/audio/effect/6.0/xml/audio_effects_conf.xsd b/audio/effect/6.0/xml/audio_effects_conf.xsd
index fcfecda..eeaaf63 100644
--- a/audio/effect/6.0/xml/audio_effects_conf.xsd
+++ b/audio/effect/6.0/xml/audio_effects_conf.xsd
@@ -255,10 +255,8 @@
     </xs:annotation>
     <xs:complexContent>
       <xs:extension base="aec:streamProcessingType">
-         <xs:complexType>
-             <xs:attribute name="address" type="xs:string" use="required"/>
-             <xs:attribute name="type" type="aec:deviceType" use="required"/>
-         </xs:complexType>
+         <xs:attribute name="address" type="xs:string" use="required"/>
+         <xs:attribute name="type" type="aec:deviceType" use="required"/>
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
@@ -322,4 +320,4 @@
       <xs:field xpath="@effect"/>
     </xs:keyref>
   </xs:element>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
diff --git a/automotive/evs/1.1/types.hal b/automotive/evs/1.1/types.hal
index f88d223..aafdb70 100644
--- a/automotive/evs/1.1/types.hal
+++ b/automotive/evs/1.1/types.hal
@@ -69,6 +69,8 @@
      * Time that this buffer is being filled.
      */
     int64_t timestamp;
+
+    vec<uint8_t> metadata;
 };
 
 /**
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index e325889..8e57901 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -85,20 +85,6 @@
     ],
 }
 
-// VHal virtualization utils
-cc_library_static {
-    name: "android.hardware.automotive.vehicle@2.0-virtualization-utils",
-    vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
-    srcs: [
-        "impl/vhal_v2_0/virtualization/Utils.cpp",
-    ],
-    export_include_dirs: ["impl"],
-    shared_libs: [
-        "libbase",
-    ],
-}
-
 cc_test {
     name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
     vendor: true,
@@ -153,59 +139,3 @@
         "libqemu_pipe",
     ],
 }
-
-cc_binary {
-    name: "android.hardware.automotive.vehicle@2.0-virtualization-service",
-    defaults: ["vhal_v2_0_defaults"],
-    init_rc: ["android.hardware.automotive.vehicle@2.0-virtualization-service.rc"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: [
-        "impl/vhal_v2_0/virtualization/GrpcVehicleClient.cpp",
-        "VirtualizedVehicleService.cpp",
-    ],
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "libjsoncpp",
-        "libprotobuf-cpp-full",
-        "libgrpc++",
-    ],
-    static_libs: [
-        "android.hardware.automotive.vehicle@2.0-manager-lib",
-        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
-        "android.hardware.automotive.vehicle@2.0-grpc",
-        "android.hardware.automotive.vehicle@2.0-virtualization-utils",
-        "libqemu_pipe",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.automotive.vehicle@2.0-virtualization-grpc-server",
-    init_rc: ["android.hardware.automotive.vehicle@2.0-virtualization-grpc-server.rc"],
-    defaults: ["vhal_v2_0_defaults"],
-    vendor: true,
-    relative_install_path: "hw",
-    srcs: [
-        "impl/vhal_v2_0/virtualization/GrpcVehicleServer.cpp",
-        "VirtualizationGrpcServer.cpp",
-    ],
-    shared_libs: [
-        "libbase",
-        "libjsoncpp",
-        "libprotobuf-cpp-full",
-        "libgrpc++",
-    ],
-    static_libs: [
-        "android.hardware.automotive.vehicle@2.0-manager-lib",
-        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
-        "android.hardware.automotive.vehicle@2.0-grpc",
-        "android.hardware.automotive.vehicle@2.0-virtualization-utils",
-    ],
-    cflags: [
-        "-Wno-unused-parameter",
-    ],
-}
diff --git a/automotive/vehicle/2.0/default/VirtualizationGrpcServer.cpp b/automotive/vehicle/2.0/default/VirtualizationGrpcServer.cpp
deleted file mode 100644
index fb02c58..0000000
--- a/automotive/vehicle/2.0/default/VirtualizationGrpcServer.cpp
+++ /dev/null
@@ -1,15 +0,0 @@
-#include <android-base/logging.h>
-
-#include "vhal_v2_0/virtualization/GrpcVehicleServer.h"
-#include "vhal_v2_0/virtualization/Utils.h"
-
-int main(int argc, char* argv[]) {
-    namespace vhal_impl = android::hardware::automotive::vehicle::V2_0::impl;
-
-    auto serverInfo = vhal_impl::VsockServerInfo::fromCommandLine(argc, argv);
-    CHECK(serverInfo.has_value()) << "Invalid server CID/port combination";
-
-    auto server = vhal_impl::makeGrpcVehicleServer(serverInfo->toUri());
-    server->Start();
-    return 0;
-}
diff --git a/automotive/vehicle/2.0/default/VirtualizedVehicleService.cpp b/automotive/vehicle/2.0/default/VirtualizedVehicleService.cpp
deleted file mode 100644
index 68813c9..0000000
--- a/automotive/vehicle/2.0/default/VirtualizedVehicleService.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include <vhal_v2_0/EmulatedVehicleConnector.h>
-#include <vhal_v2_0/EmulatedVehicleHal.h>
-#include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/virtualization/GrpcVehicleClient.h>
-#include <vhal_v2_0/virtualization/Utils.h>
-
-using namespace android;
-using namespace android::hardware;
-using namespace android::hardware::automotive::vehicle::V2_0;
-
-int main(int argc, char* argv[]) {
-    namespace vhal_impl = android::hardware::automotive::vehicle::V2_0::impl;
-
-    auto serverInfo = vhal_impl::VsockServerInfo::fromRoPropertyStore();
-    CHECK(serverInfo.has_value()) << "Invalid server CID/port combination";
-
-    auto store = std::make_unique<VehiclePropertyStore>();
-    auto connector = impl::makeGrpcVehicleClient(serverInfo->toUri());
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
-    auto emulator = std::make_unique<impl::VehicleEmulator>(hal.get());
-    auto service = std::make_unique<VehicleHalManager>(hal.get());
-
-    configureRpcThreadpool(4, true /* callerWillJoin */);
-
-    LOG(INFO) << "Registering as service...";
-    status_t status = service->registerAsService();
-
-    if (status != OK) {
-        LOG(ERROR) << "Unable to register vehicle service (" << status << ")";
-        return 1;
-    }
-
-    LOG(INFO) << "Ready";
-    joinRpcThreadpool();
-
-    return 1;
-}
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-grpc-server.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-grpc-server.rc
deleted file mode 100644
index 1101b08..0000000
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-grpc-server.rc
+++ /dev/null
@@ -1,10 +0,0 @@
-# It is an interim state to run GRPC server as an Android service.
-# Eventually it will run outside of Android (e.g., AGL),
-# so the command line arguments are expected, though not conventionally used in Android
-service vendor.vehicle-hal-2.0-server \
-        /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-virtualization-grpc-server \
-        -server_cid ${ro.vendor.vehiclehal.server.cid:-pleaseconfigurethis} \
-        -server_port ${ro.vendor.vehiclehal.server.port:-pleaseconfigurethis}
-    class hal
-    user vehicle_network
-    group system inet
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-service.rc
deleted file mode 100644
index 234de59..0000000
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-virtualization-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-virtualization-service
-    class hal
-    user vehicle_network
-    group system inet
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
index d40f122..00b5afe 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleConnector.h
@@ -65,6 +65,12 @@
     // updateStatus is true if and only if the value is
     // generated by car (ECU/fake generator/injected)
     virtual void onPropertyValue(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // Dump method forwarded from HIDL's debug()
+    // If implemented, it must return whether the caller should dump its state.
+    virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
+        return true;
+    }
 };
 
 /**
@@ -97,6 +103,13 @@
     // updateStatus is true if and only if the value is
     // generated by car (ECU/fake generator/injected)
     virtual void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) = 0;
+
+    // Dump method forwarded from HIDL's debug()
+    // If implemented, it must return whether the caller should dump its state.
+    virtual bool onDump(const hidl_handle& /* handle */,
+                        const hidl_vec<hidl_string>& /* options */) {
+        return true;
+    }
 };
 
 /**
@@ -134,6 +147,10 @@
         return this->onPropertyValue(value, updateStatus);
     }
 
+    bool dump(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override {
+        return this->onDump(handle, options);
+    }
+
     // To be implemented:
     // virtual std::vector<VehiclePropConfig> onGetAllPropertyConfig() = 0;
     // virtual void onPropertyValue(const VehiclePropValue& value) = 0;
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
index fd28483..fe01867 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
@@ -70,6 +70,26 @@
      */
     virtual void onCreate() {}
 
+    /**
+     * Dump method forwarded from HIDL's debug().
+     *
+     * By default it doesn't dump anything and let caller dump its properties, but it could be
+     * override to change the behavior. For example:
+     *
+     * - To augment caller's dump, it should dump its state and return true.
+     * - To not dump anything at all, it should just return false.
+     * - To provide custom dump (like dumping just specific state or executing a custom command),
+     *   it should check if options is not empty, handle the options accordingly, then return false.
+     *
+     * @param handle handle used to dump the contents.
+     * @param options options passed to dump.
+     *
+     * @return whether the caller should dump its state.
+     */
+    virtual bool dump(const hidl_handle& /* handle */, const hidl_vec<hidl_string>& /* options */) {
+        return true;
+    }
+
     void init(
         VehiclePropValuePool* valueObjectPool,
         const HalEventFunction& onHalEvent,
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index 4249a61..5bebd1e 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -28,6 +28,8 @@
 
 #include <hwbinder/IPCThreadState.h>
 
+#include <utils/SystemClock.h>
+
 #include "VehicleUtils.h"
 
 // TODO: figure out how to include private/android_filesystem_config.h instead...
@@ -184,11 +186,19 @@
 }
 
 Return<void> VehicleHalManager::debug(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
-    if (fd.getNativeHandle() != nullptr && fd->numFds > 0) {
-        cmdDump(fd->data[0], options);
-    } else {
+    if (fd.getNativeHandle() == nullptr || fd->numFds == 0) {
         ALOGE("Invalid parameters passed to debug()");
+        return Void();
     }
+
+    bool shouldContinue = mHal->dump(fd, options);
+    if (!shouldContinue) {
+        ALOGI("Dumped HAL only");
+        return Void();
+    }
+
+    // Do our dump
+    cmdDump(fd->data[0], options);
     return Void();
 }
 
@@ -247,10 +257,11 @@
     dprintf(fd, "--get <PROP1> [PROP2] [PROPN]: dumps the value of specific properties \n");
     // TODO: support other formats (int64, float, bytes)
     dprintf(fd,
-            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>]: sets the value of property PROP, using"
-            " arbitrary number of key/value parameters (i for int32, s for string). Notice that "
-            "the string value can be set just once, while the other can have multiple values "
-            "(so they're used in the respective array)\n");
+            "--set <PROP> <i|s> <VALUE_1> [<i|s> <VALUE_N>] [a AREA_ID] : sets the value of "
+            "property PROP, using arbitrary number of key/value parameters (i for int32, "
+            "s for string) and an optional area.\n"
+            "Notice that the string value can be set just once, while the other can have multiple "
+            "values (so they're used in the respective array)\n");
 }
 
 void VehicleHalManager::cmdListAllProperties(int fd) const {
@@ -352,13 +363,13 @@
 
     VehiclePropValue prop;
     if (!safelyParseInt(fd, 1, options[1], &prop.prop)) return;
-    prop.timestamp = 0;
-    prop.areaId = 0;  // TODO: add option to pass areaId as parameter
+    prop.timestamp = elapsedRealtimeNano();
     prop.status = VehiclePropertyStatus::AVAILABLE;
 
-    // First pass calculate sizes
+    // First pass: calculate sizes
     int sizeInt32 = 0;
     int stringIndex = 0;
+    int areaIndex = 0;
     for (int i = 2, kv = 1; kv <= numberValues; kv++) {
         // iterate through the kv=1..n key/value pairs, accessing indexes i / i+1 at each step
         std::string type = options[i];
@@ -374,6 +385,15 @@
                 return;
             }
             stringIndex = i;
+        } else if (EqualsIgnoreCase(type, "a")) {
+            if (areaIndex != 0) {
+                dprintf(fd,
+                        "defining area value (%s) again at index %d (already defined at %d=%s"
+                        ")\n",
+                        value.c_str(), i, areaIndex, options[areaIndex + 1].c_str());
+                return;
+            }
+            areaIndex = i;
         } else {
             dprintf(fd, "invalid (%s) type at index %d\n", type.c_str(), i);
             return;
@@ -395,6 +415,8 @@
             prop.value.int32Values[indexInt32++] = safeInt;
         } else if (EqualsIgnoreCase(type, "s")) {
             prop.value.stringValue = value;
+        } else if (EqualsIgnoreCase(type, "a")) {
+            if (!safelyParseInt(fd, valueIndex, value, &prop.areaId)) return;
         }
         i += 2;
     }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index e19987c..785f0e0 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -76,6 +76,7 @@
 constexpr int WHEEL_FRONT_RIGHT = (int)VehicleAreaWheel::RIGHT_FRONT;
 constexpr int WHEEL_REAR_LEFT = (int)VehicleAreaWheel::LEFT_REAR;
 constexpr int WHEEL_REAR_RIGHT = (int)VehicleAreaWheel::RIGHT_REAR;
+constexpr int INITIAL_USER_INFO = (int)VehicleProperty::INITIAL_USER_INFO;
 
 /**
  * This property is used for test purpose to generate fake events. Here is the test package that
@@ -990,6 +991,16 @@
                                   (int)VehicleVendorPermission::PERMISSION_DEFAULT},
                  },
          .initialValue = {.int32Values = {1}}},
+
+        {
+                .config =
+                        {
+                                .prop = toInt(VehicleProperty::INITIAL_USER_INFO),
+                                .access = VehiclePropertyAccess::READ_WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
index d9867bd..7f90914 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.cpp
@@ -13,6 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#define LOG_TAG "automotive.vehicle@2.0-connector"
+
+#include <fstream>
+
 #include <android-base/logging.h>
 #include <utils/SystemClock.h>
 
@@ -261,6 +266,8 @@
                     break;
             }
             break;
+        case INITIAL_USER_INFO:
+            return onSetInitialUserInfo(value, updateStatus);
         default:
             break;
     }
@@ -274,6 +281,135 @@
     return StatusCode::OK;
 }
 
+/**
+ * INITIAL_USER_INFO is called by Android when it starts, and it's expecting a property change
+ * indicating what the initial user should be.
+ *
+ * During normal circumstances, the emulator will reply right away, passing a response if
+ * InitialUserInfoResponseAction::DEFAULT (so Android could use its own logic to decide which user
+ * to boot).
+ *
+ * But during development / testing, the behavior can be changed using lshal dump, which must use
+ * the areaId to indicate what should happen next.
+ *
+ * So, the behavior of set(INITIAL_USER_INFO) is:
+ *
+ * - if it has an areaId, store the property into mInitialUserResponseFromCmd (as it was called by
+ *   lshal).
+ * - else if mInitialUserResponseFromCmd is not set, return a response with the same request id and
+ *   InitialUserInfoResponseAction::DEFAULT
+ * - else the behavior is defined by the areaId on mInitialUserResponseFromCmd:
+ * - if it's 1, reply with mInitialUserResponseFromCmd and the right request id
+ * - if it's 2, reply with mInitialUserResponseFromCmd but a wrong request id (so Android can test
+ *   this error scenario)
+ * - if it's 3, then don't send a property change (so Android can emulate a timeout)
+ *
+ */
+StatusCode EmulatedVehicleServer::onSetInitialUserInfo(const VehiclePropValue& value,
+                                                       bool updateStatus) {
+    // TODO: LOG calls below might be more suited to be DEBUG, but those are not being logged
+    // (even when explicitly calling setprop log.tag. As this class should be using ALOG instead of
+    // LOG, it's not worth investigating why...
+
+    if (value.value.int32Values.size() == 0) {
+        LOG(ERROR) << "set(INITIAL_USER_INFO): no int32values, ignoring it: " << toString(value);
+        return StatusCode::INVALID_ARG;
+    }
+
+    if (value.areaId != 0) {
+        LOG(INFO) << "set(INITIAL_USER_INFO) called from lshal; storing it: " << toString(value);
+        mInitialUserResponseFromCmd.reset(new VehiclePropValue(value));
+        return StatusCode::OK;
+    }
+    LOG(INFO) << "set(INITIAL_USER_INFO) called from Android: " << toString(value);
+
+    int32_t requestId = value.value.int32Values[0];
+
+    // Create the update property and set common values
+    auto updatedValue = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
+    updatedValue->prop = INITIAL_USER_INFO;
+    updatedValue->timestamp = elapsedRealtimeNano();
+
+    if (mInitialUserResponseFromCmd == nullptr) {
+        updatedValue->value.int32Values.resize(2);
+        updatedValue->value.int32Values[0] = requestId;
+        updatedValue->value.int32Values[1] = (int32_t)InitialUserInfoResponseAction::DEFAULT;
+        LOG(INFO) << "no lshal response; returning InitialUserInfoResponseAction::DEFAULT: "
+                  << toString(*updatedValue);
+        onPropertyValueFromCar(*updatedValue, updateStatus);
+        return StatusCode::OK;
+    }
+
+    // mInitialUserResponseFromCmd is used for just one request
+    std::unique_ptr<VehiclePropValue> response = std::move(mInitialUserResponseFromCmd);
+
+    // TODO(b/138709788): rather than populate the raw values directly, it should use the
+    // libraries that convert a InitialUserInfoResponse into a VehiclePropValue)
+
+    switch (response->areaId) {
+        case 1:
+            LOG(INFO) << "returning response with right request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = requestId;
+            break;
+        case 2:
+            LOG(INFO) << "returning response with wrong request id";
+            *updatedValue = *response;
+            updatedValue->areaId = 0;
+            updatedValue->value.int32Values[0] = -requestId;
+            break;
+        case 3:
+            LOG(INFO) << "not generating a property change event because of lshal prop: "
+                      << toString(*response);
+            return StatusCode::OK;
+        default:
+            LOG(ERROR) << "invalid action on lshal response: " << toString(*response);
+            return StatusCode::INTERNAL_ERROR;
+    }
+
+    LOG(INFO) << "updating property to: " << toString(*updatedValue);
+    onPropertyValueFromCar(*updatedValue, updateStatus);
+    return StatusCode::OK;
+}
+
+bool EmulatedVehicleServer::onDump(const hidl_handle& handle,
+                                   const hidl_vec<hidl_string>& options) {
+    int fd = handle->data[0];
+
+    if (options.size() > 0) {
+        if (options[0] == "--help") {
+            dprintf(fd, "Emulator-specific usage:\n");
+            dprintf(fd, "--user-hal: dumps state used for user management \n");
+            dprintf(fd, "\n");
+            // Include caller's help options
+            return true;
+        } else if (options[0] == "--user-hal") {
+            dumpUserHal(fd, "");
+            return false;
+
+        } else {
+            // Let caller handle the options...
+            return true;
+        }
+    }
+
+    dprintf(fd, "Emulator-specific state:\n");
+    dumpUserHal(fd, "  ");
+    dprintf(fd, "\n");
+
+    return true;
+}
+
+void EmulatedVehicleServer::dumpUserHal(int fd, std::string indent) {
+    if (mInitialUserResponseFromCmd != nullptr) {
+        dprintf(fd, "%sInitial User Info: %s\n", indent.c_str(),
+                toString(*mInitialUserResponseFromCmd).c_str());
+    } else {
+        dprintf(fd, "%sNo Initial User Info\n", indent.c_str());
+    }
+}
+
 EmulatedPassthroughConnectorPtr makeEmulatedPassthroughConnector() {
     return std::make_unique<EmulatedPassthroughConnector>();
 }
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
index 5fc6493..4850d32 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleConnector.h
@@ -54,6 +54,8 @@
 
     StatusCode onSetProperty(const VehiclePropValue& value, bool updateStatus) override;
 
+    bool onDump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
+
     // Set the Property Value Pool used in this server
     void setValuePool(VehiclePropValuePool* valuePool);
 
@@ -77,6 +79,11 @@
             std::bind(&EmulatedVehicleServer::onFakeValueGenerated, this, std::placeholders::_1)};
 
     VehiclePropValuePool* mValuePool{nullptr};
+
+    // TODO(b/146207078): it might be clearer to move members below to an EmulatedUserHal class
+    std::unique_ptr<VehiclePropValue> mInitialUserResponseFromCmd;
+    StatusCode onSetInitialUserInfo(const VehiclePropValue& value, bool updateStatus);
+    void dumpUserHal(int fd, std::string indent);
 };
 
 // Helper functions
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 5c16bf7..692c7f7 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
@@ -131,6 +131,10 @@
     return v;
 }
 
+bool EmulatedVehicleHal::dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) {
+    return mVehicleClient->dump(fd, options);
+}
+
 StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
     constexpr bool updateStatus = false;
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index a8378da..ebc405e 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -57,6 +57,7 @@
     StatusCode set(const VehiclePropValue& propValue) override;
     StatusCode subscribe(int32_t property, float sampleRate) override;
     StatusCode unsubscribe(int32_t property) override;
+    bool dump(const hidl_handle& fd, const hidl_vec<hidl_string>& options) override;
 
     //  Methods from EmulatedVehicleHalIface
     bool setPropertyFromVehicle(const VehiclePropValue& propValue) override;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.cpp
deleted file mode 100644
index e329c5b..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.cpp
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "GrpcVehicleClient.h"
-
-#include <condition_variable>
-#include <mutex>
-
-#include <android-base/logging.h>
-#include <grpc++/grpc++.h>
-
-#include "VehicleServer.grpc.pb.h"
-#include "VehicleServer.pb.h"
-#include "vhal_v2_0/ProtoMessageConverter.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-static std::shared_ptr<::grpc::ChannelCredentials> getChannelCredentials() {
-    // TODO(chenhaosjtuacm): get secured credentials here
-    return ::grpc::InsecureChannelCredentials();
-}
-
-class GrpcVehicleClientImpl : public EmulatedVehicleClient {
-  public:
-    GrpcVehicleClientImpl(const std::string& addr)
-        : mServiceAddr(addr),
-          mGrpcChannel(::grpc::CreateChannel(mServiceAddr, getChannelCredentials())),
-          mGrpcStub(vhal_proto::VehicleServer::NewStub(mGrpcChannel)) {
-        StartValuePollingThread();
-    }
-
-    ~GrpcVehicleClientImpl() {
-        mShuttingDownFlag.store(true);
-        mShutdownCV.notify_all();
-        if (mPollingThread.joinable()) {
-            mPollingThread.join();
-        }
-    }
-
-    // methods from IVehicleClient
-
-    std::vector<VehiclePropConfig> getAllPropertyConfig() const override;
-
-    StatusCode setProperty(const VehiclePropValue& value, bool updateStatus) override;
-
-  private:
-    void StartValuePollingThread();
-
-    // private data members
-
-    std::string mServiceAddr;
-    std::shared_ptr<::grpc::Channel> mGrpcChannel;
-    std::unique_ptr<vhal_proto::VehicleServer::Stub> mGrpcStub;
-    std::thread mPollingThread;
-
-    std::mutex mShutdownMutex;
-    std::condition_variable mShutdownCV;
-    std::atomic<bool> mShuttingDownFlag{false};
-};
-
-std::unique_ptr<EmulatedVehicleClient> makeGrpcVehicleClient(const std::string& addr) {
-    return std::make_unique<GrpcVehicleClientImpl>(addr);
-}
-
-std::vector<VehiclePropConfig> GrpcVehicleClientImpl::getAllPropertyConfig() const {
-    std::vector<VehiclePropConfig> configs;
-    ::grpc::ClientContext context;
-    auto config_stream = mGrpcStub->GetAllPropertyConfig(&context, ::google::protobuf::Empty());
-    vhal_proto::VehiclePropConfig protoConfig;
-    while (config_stream->Read(&protoConfig)) {
-        VehiclePropConfig config;
-        proto_msg_converter::fromProto(&config, protoConfig);
-        configs.emplace_back(std::move(config));
-    }
-    auto grpc_status = config_stream->Finish();
-    if (!grpc_status.ok()) {
-        LOG(ERROR) << __func__
-                   << ": GRPC GetAllPropertyConfig Failed: " << grpc_status.error_message();
-        configs.clear();
-    }
-
-    return configs;
-}
-
-StatusCode GrpcVehicleClientImpl::setProperty(const VehiclePropValue& value, bool updateStatus) {
-    ::grpc::ClientContext context;
-    vhal_proto::WrappedVehiclePropValue wrappedProtoValue;
-    vhal_proto::VehicleHalCallStatus vhal_status;
-    proto_msg_converter::toProto(wrappedProtoValue.mutable_value(), value);
-    wrappedProtoValue.set_update_status(updateStatus);
-
-    auto grpc_status = mGrpcStub->SetProperty(&context, wrappedProtoValue, &vhal_status);
-    if (!grpc_status.ok()) {
-        LOG(ERROR) << __func__ << ": GRPC SetProperty Failed: " << grpc_status.error_message();
-        return StatusCode::INTERNAL_ERROR;
-    }
-
-    return static_cast<StatusCode>(vhal_status.status_code());
-}
-
-void GrpcVehicleClientImpl::StartValuePollingThread() {
-    mPollingThread = std::thread([this]() {
-        while (!mShuttingDownFlag.load()) {
-            ::grpc::ClientContext context;
-
-            std::atomic<bool> rpc_ok{true};
-            std::thread shuttingdown_watcher([this, &rpc_ok, &context]() {
-                std::unique_lock<std::mutex> shutdownLock(mShutdownMutex);
-                mShutdownCV.wait(shutdownLock, [this, &rpc_ok]() {
-                    return !rpc_ok.load() || mShuttingDownFlag.load();
-                });
-                context.TryCancel();
-            });
-
-            auto value_stream =
-                    mGrpcStub->StartPropertyValuesStream(&context, ::google::protobuf::Empty());
-            vhal_proto::WrappedVehiclePropValue wrappedProtoValue;
-            while (!mShuttingDownFlag.load() && value_stream->Read(&wrappedProtoValue)) {
-                VehiclePropValue value;
-                proto_msg_converter::fromProto(&value, wrappedProtoValue.value());
-                onPropertyValue(value, wrappedProtoValue.update_status());
-            }
-
-            rpc_ok.store(false);
-            mShutdownCV.notify_all();
-            shuttingdown_watcher.join();
-
-            auto grpc_status = value_stream->Finish();
-            // never reach here until connection lost
-            LOG(ERROR) << __func__
-                       << ": GRPC Value Streaming Failed: " << grpc_status.error_message();
-
-            // try to reconnect
-        }
-    });
-}
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.h
deleted file mode 100644
index 14eae7f..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleClient.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleClient_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleClient_H_
-
-#include "vhal_v2_0/EmulatedVehicleConnector.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-std::unique_ptr<EmulatedVehicleClient> makeGrpcVehicleClient(const std::string& addr);
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleClient_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.cpp
deleted file mode 100644
index e30b3be..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.cpp
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "GrpcVehicleServer.h"
-
-#include <condition_variable>
-#include <mutex>
-#include <shared_mutex>
-
-#include <android-base/logging.h>
-#include <grpc++/grpc++.h>
-
-#include "VehicleServer.grpc.pb.h"
-#include "VehicleServer.pb.h"
-#include "vhal_v2_0/ProtoMessageConverter.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-class GrpcVehicleServerImpl : public GrpcVehicleServer, public vhal_proto::VehicleServer::Service {
-  public:
-    GrpcVehicleServerImpl(const std::string& addr) : mServiceAddr(addr) {
-        setValuePool(&mValueObjectPool);
-    }
-
-    // method from GrpcVehicleServer
-    void Start() override;
-
-    // method from IVehicleServer
-    void onPropertyValueFromCar(const VehiclePropValue& value, bool updateStatus) override;
-
-    // methods from vhal_proto::VehicleServer::Service
-
-    ::grpc::Status GetAllPropertyConfig(
-            ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-            ::grpc::ServerWriter<vhal_proto::VehiclePropConfig>* stream) override;
-
-    ::grpc::Status SetProperty(::grpc::ServerContext* context,
-                               const vhal_proto::WrappedVehiclePropValue* wrappedPropValue,
-                               vhal_proto::VehicleHalCallStatus* status) override;
-
-    ::grpc::Status StartPropertyValuesStream(
-            ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-            ::grpc::ServerWriter<vhal_proto::WrappedVehiclePropValue>* stream) override;
-
-  private:
-    // We keep long-lasting connection for streaming the prop values.
-    // For us, each connection can be represented as a function to send the new value, and
-    // an ID to identify this connection
-    struct ConnectionDescriptor {
-        using ValueWriterType = std::function<bool(const vhal_proto::WrappedVehiclePropValue&)>;
-
-        ConnectionDescriptor(ValueWriterType&& value_writer)
-            : mValueWriter(std::move(value_writer)),
-              mConnectionID(CONNECTION_ID_COUNTER.fetch_add(1)) {}
-
-        ConnectionDescriptor(const ConnectionDescriptor&) = delete;
-
-        ConnectionDescriptor& operator=(const ConnectionDescriptor&) = delete;
-
-        // This move constructor is NOT THREAD-SAFE, which means it cannot be moved
-        // while using. Since the connection descriptors are pretected by mConnectionMutex
-        // then we are fine here
-        ConnectionDescriptor(ConnectionDescriptor&& cd)
-            : mValueWriter(std::move(cd.mValueWriter)),
-              mConnectionID(cd.mConnectionID),
-              mIsAlive(cd.mIsAlive.load()) {
-            cd.mIsAlive.store(false);
-        }
-
-        ValueWriterType mValueWriter;
-        uint64_t mConnectionID;
-        std::atomic<bool> mIsAlive{true};
-
-        static std::atomic<uint64_t> CONNECTION_ID_COUNTER;
-    };
-
-    std::string mServiceAddr;
-    VehiclePropValuePool mValueObjectPool;
-    mutable std::shared_mutex mConnectionMutex;
-    mutable std::shared_mutex mWriterMutex;
-    std::list<ConnectionDescriptor> mValueStreamingConnections;
-};
-
-std::atomic<uint64_t> GrpcVehicleServerImpl::ConnectionDescriptor::CONNECTION_ID_COUNTER = 0;
-
-static std::shared_ptr<::grpc::ServerCredentials> getServerCredentials() {
-    // TODO(chenhaosjtuacm): get secured credentials here
-    return ::grpc::InsecureServerCredentials();
-}
-
-GrpcVehicleServerPtr makeGrpcVehicleServer(const std::string& addr) {
-    return std::make_unique<GrpcVehicleServerImpl>(addr);
-}
-
-void GrpcVehicleServerImpl::Start() {
-    ::grpc::ServerBuilder builder;
-    builder.RegisterService(this);
-    builder.AddListeningPort(mServiceAddr, getServerCredentials());
-    std::unique_ptr<::grpc::Server> server(builder.BuildAndStart());
-
-    server->Wait();
-}
-
-void GrpcVehicleServerImpl::onPropertyValueFromCar(const VehiclePropValue& value,
-                                                   bool updateStatus) {
-    vhal_proto::WrappedVehiclePropValue wrappedPropValue;
-    proto_msg_converter::toProto(wrappedPropValue.mutable_value(), value);
-    wrappedPropValue.set_update_status(updateStatus);
-    std::shared_lock read_lock(mConnectionMutex);
-
-    bool has_terminated_connections = 0;
-
-    for (auto& connection : mValueStreamingConnections) {
-        auto writeOK = connection.mValueWriter(wrappedPropValue);
-        if (!writeOK) {
-            LOG(ERROR) << __func__ << ": Server Write failed, connection lost. ID: "
-                       << connection.mConnectionID;
-            has_terminated_connections = true;
-            connection.mIsAlive.store(false);
-        }
-    }
-
-    if (!has_terminated_connections) {
-        return;
-    }
-
-    read_lock.unlock();
-
-    std::unique_lock write_lock(mConnectionMutex);
-
-    for (auto itr = mValueStreamingConnections.begin(); itr != mValueStreamingConnections.end();) {
-        if (!itr->mIsAlive.load()) {
-            itr = mValueStreamingConnections.erase(itr);
-        } else {
-            ++itr;
-        }
-    }
-}
-
-::grpc::Status GrpcVehicleServerImpl::GetAllPropertyConfig(
-        ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-        ::grpc::ServerWriter<vhal_proto::VehiclePropConfig>* stream) {
-    auto configs = onGetAllPropertyConfig();
-    for (auto& config : configs) {
-        vhal_proto::VehiclePropConfig protoConfig;
-        proto_msg_converter::toProto(&protoConfig, config);
-        if (!stream->Write(protoConfig)) {
-            return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
-        }
-    }
-
-    return ::grpc::Status::OK;
-}
-
-::grpc::Status GrpcVehicleServerImpl::SetProperty(
-        ::grpc::ServerContext* context, const vhal_proto::WrappedVehiclePropValue* wrappedPropValue,
-        vhal_proto::VehicleHalCallStatus* status) {
-    VehiclePropValue value;
-    proto_msg_converter::fromProto(&value, wrappedPropValue->value());
-
-    auto set_status = static_cast<int32_t>(onSetProperty(value, wrappedPropValue->update_status()));
-    if (!vhal_proto::VehicleHalStatusCode_IsValid(set_status)) {
-        return ::grpc::Status(::grpc::StatusCode::INTERNAL, "Unknown status code");
-    }
-
-    status->set_status_code(static_cast<vhal_proto::VehicleHalStatusCode>(set_status));
-
-    return ::grpc::Status::OK;
-}
-
-::grpc::Status GrpcVehicleServerImpl::StartPropertyValuesStream(
-        ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
-        ::grpc::ServerWriter<vhal_proto::WrappedVehiclePropValue>* stream) {
-    std::mutex terminateMutex;
-    std::condition_variable terminateCV;
-    std::unique_lock<std::mutex> terminateLock(terminateMutex);
-    bool terminated{false};
-
-    auto callBack = [stream, &terminateMutex, &terminateCV, &terminated,
-                     this](const vhal_proto::WrappedVehiclePropValue& value) {
-        std::unique_lock lock(mWriterMutex);
-        if (!stream->Write(value)) {
-            std::unique_lock<std::mutex> terminateLock(terminateMutex);
-            terminated = true;
-            terminateLock.unlock();
-            terminateCV.notify_all();
-            return false;
-        }
-        return true;
-    };
-
-    // Register connection
-    std::unique_lock lock(mConnectionMutex);
-    auto& conn = mValueStreamingConnections.emplace_back(std::move(callBack));
-    lock.unlock();
-
-    // Never stop until connection lost
-    terminateCV.wait(terminateLock, [&terminated]() { return terminated; });
-
-    LOG(ERROR) << __func__ << ": Stream lost, ID : " << conn.mConnectionID;
-
-    return ::grpc::Status(::grpc::StatusCode::ABORTED, "Connection lost.");
-}
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.h
deleted file mode 100644
index 32f4eb2..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/GrpcVehicleServer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleServer_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleServer_H_
-
-#include "vhal_v2_0/EmulatedVehicleConnector.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace impl {
-
-// Connect to the Vehicle Client via GRPC
-class GrpcVehicleServer : public EmulatedVehicleServer {
-  public:
-    // Start listening incoming calls, should never return if working normally
-    virtual void Start() = 0;
-};
-
-using GrpcVehicleServerPtr = std::unique_ptr<GrpcVehicleServer>;
-
-GrpcVehicleServerPtr makeGrpcVehicleServer(const std::string& addr);
-
-}  // namespace impl
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_virtialization_GrpcVehicleServer_H_
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.cpp
deleted file mode 100644
index 184d8a4..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Utils.h"
-
-#include <cutils/properties.h>
-
-#include <getopt.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sstream>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-namespace impl {
-
-std::string VsockServerInfo::toUri() {
-    std::stringstream uri_stream;
-    uri_stream << "vsock:" << serverCid << ":" << serverPort;
-    return uri_stream.str();
-}
-
-static std::optional<unsigned> parseUnsignedIntFromString(const char* optarg, const char* name) {
-    auto v = strtoul(optarg, nullptr, 0);
-    if (((v == ULONG_MAX) && (errno == ERANGE)) || (v > UINT_MAX)) {
-        LOG(WARNING) << name << " value is out of range: " << optarg;
-    } else if (v != 0) {
-        return v;
-    } else {
-        LOG(WARNING) << name << " value is invalid or missing: " << optarg;
-    }
-
-    return std::nullopt;
-}
-
-static std::optional<unsigned> getNumberFromProperty(const char* key) {
-    auto value = property_get_int64(key, -1);
-    if ((value <= 0) || (value > UINT_MAX)) {
-        LOG(WARNING) << key << " is missing or out of bounds";
-        return std::nullopt;
-    }
-
-    return static_cast<unsigned int>(value);
-};
-
-std::optional<VsockServerInfo> VsockServerInfo::fromCommandLine(int argc, char* argv[]) {
-    std::optional<unsigned int> cid;
-    std::optional<unsigned int> port;
-
-    // unique values to identify the options
-    constexpr int OPT_VHAL_SERVER_CID = 1001;
-    constexpr int OPT_VHAL_SERVER_PORT_NUMBER = 1002;
-
-    struct option longOptions[] = {
-            {"server_cid", 1, 0, OPT_VHAL_SERVER_CID},
-            {"server_port", 1, 0, OPT_VHAL_SERVER_PORT_NUMBER},
-            {},
-    };
-
-    int optValue;
-    while ((optValue = getopt_long_only(argc, argv, ":", longOptions, 0)) != -1) {
-        switch (optValue) {
-            case OPT_VHAL_SERVER_CID:
-                cid = parseUnsignedIntFromString(optarg, "cid");
-                break;
-            case OPT_VHAL_SERVER_PORT_NUMBER:
-                port = parseUnsignedIntFromString(optarg, "port");
-                break;
-            default:
-                // ignore other options
-                break;
-        }
-    }
-
-    if (cid && port) {
-        return VsockServerInfo{*cid, *port};
-    }
-    return std::nullopt;
-}
-
-std::optional<VsockServerInfo> VsockServerInfo::fromRoPropertyStore() {
-    constexpr const char* VHAL_SERVER_CID_PROPERTY_KEY = "ro.vendor.vehiclehal.server.cid";
-    constexpr const char* VHAL_SERVER_PORT_PROPERTY_KEY = "ro.vendor.vehiclehal.server.port";
-
-    const auto cid = getNumberFromProperty(VHAL_SERVER_CID_PROPERTY_KEY);
-    const auto port = getNumberFromProperty(VHAL_SERVER_PORT_PROPERTY_KEY);
-
-    if (cid && port) {
-        return VsockServerInfo{*cid, *port};
-    }
-    return std::nullopt;
-}
-
-}  // namespace impl
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.h
deleted file mode 100644
index 8a8bce7..0000000
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/virtualization/Utils.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_0_impl_virtualization_Utils_H_
-#define android_hardware_automotive_vehicle_V2_0_impl_virtualization_Utils_H_
-
-#include <optional>
-#include <string>
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-namespace impl {
-
-struct VsockServerInfo {
-    unsigned int serverCid{0};
-    unsigned int serverPort{0};
-
-    static std::optional<VsockServerInfo> fromCommandLine(int argc, char* argv[]);
-    static std::optional<VsockServerInfo> fromRoPropertyStore();
-
-    std::string toUri();
-};
-
-}  // namespace impl
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_virtualization_Utils_H_
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 54039e5..cf25cc8 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -22,5 +22,8 @@
         "android.hardware.bluetooth@1.0",
         "libbluetooth-types",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
index f6cd6ae..8ab2b43 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -82,33 +82,44 @@
     };                                                                \
     return EGMockFlippedComma_<decltype(invokeMock())>(invokeMock, notify);
 
+// We define this as a variadic macro in case F contains unprotected
+// commas (the same reason that we use variadic macros in other places
+// in this file).
+#define EGMOCK_RESULT_(tn, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Result
+
+// The type of argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define EGMOCK_ARG_(tn, N, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
+
 /**
  * Gmock MOCK_METHOD0 timeout-capable extension.
  */
 #define MOCK_TIMEOUT_METHOD0(Method, ...)       \
     MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
     EGMOCK_TIMEOUT_METHOD_DEF_(Method);         \
-    virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
+    virtual EGMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
 
 /**
  * Gmock MOCK_METHOD1 timeout-capable extension.
  */
-#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                 \
-    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                           \
-    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                   \
-    virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
-        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                   \
+#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                   \
+    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                             \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                     \
+    virtual EGMOCK_RESULT_(, __VA_ARGS__) Method(EGMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                     \
     }
 
 /**
  * Gmock MOCK_METHOD2 timeout-capable extension.
  */
-#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                        \
-    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                  \
-    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                          \
-    virtual GMOCK_RESULT_(, __VA_ARGS__)                                                         \
-        Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
-        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                               \
+#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                          \
+    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                    \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                            \
+    virtual EGMOCK_RESULT_(, __VA_ARGS__)                                                          \
+        Method(EGMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, EGMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                                 \
     }
 
 /**
diff --git a/current.txt b/current.txt
index 8d068d0..7d67361 100644
--- a/current.txt
+++ b/current.txt
@@ -596,7 +596,7 @@
 5f6d3097ba84cb63c430787123f4de1b31c11f90b531b98eae9a8623a5ae962a android.hardware.neuralnetworks@1.1::types
 fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
 40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
-7f7ef383268c95a1b8fe4e55c662bc806bb0ac11a154f6b049a113a44b0f024f android.hardware.neuralnetworks@1.2::types
+6c29d6fdd5445911df5456b3b84b949cdd59fca0c0b5507662f26a5cac0cf5e5 android.hardware.neuralnetworks@1.2::types
 a785a57447a81e9c130eef6904c3a5c256076c6a04588c40620ebd6fa2660d77 android.hardware.radio@1.2::types
 1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
 fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
@@ -605,14 +605,14 @@
 
 # HALs released in Android R
 e966a3437d6a98d9d9e14e9d672088771716031900c0deb55a0946c751a03a44 android.hardware.audio@6.0::types
-dd3e9280be60a5e042331c1046d13938e2cc323dc4b267cc74d544bf62fc0314 android.hardware.audio@6.0::IDevice
+7241bd4596a927cd46d4b82f5e29e2cbe57f194aa1b25555f1d1d352e8b15c61 android.hardware.audio@6.0::IDevice
 2402876cbc23c0de3690a665eca84fd3857d1808dba5cad25ce272f81ecef8c9 android.hardware.audio@6.0::IDevicesFactory
 bca5379d5065e2e08b6ad7308ffc8a71a972fc0698bec678ea32eea786d01cb5 android.hardware.audio@6.0::IPrimaryDevice
 fd1f1b29f26b42e886220f04a08086c00e5ade9d7b53f095438e578ab9d42a93 android.hardware.audio@6.0::IStream
 2df5d5866b37776f25079c0e54b54350a2abe4e025a59c9e02a7d3abe8ca00e8 android.hardware.audio@6.0::IStreamIn
 78e4138cc8307c11fc777c3bd376e581ba4ba48196b05ca1d7cdfa515c87b48a android.hardware.audio@6.0::IStreamOut
 997fdaad7a9d17ee7e01feb7031a753e2365e72ad30b11d950e9183fabdf3844 android.hardware.audio@6.0::IStreamOutCallback
-43a3303378f5b9852c2da9ac2c1d440965aab7ba02a800229e7b3c84e2167e06 android.hardware.audio.common@6.0::types
+167ed5cfb7d91db2e2bf20f1320c1a9004eeb768e26f535e0f7db94a21867d21 android.hardware.audio.common@6.0::types
 817930d58412d662cb45e641c50cb62c727e4a3e3ffe7029a53cad9677b97d58 android.hardware.audio.effect@6.0::types
 525bec6b44f1103869c269a128d51b8dccd73af5340ba863c8886c68357c7faf android.hardware.audio.effect@6.0::IAcousticEchoCancelerEffect
 8d76bbe3719d051a8e9a1dcf9244f37f5b0a491feb249fa48391edf7cb4f3131 android.hardware.audio.effect@6.0::IAutomaticGainControlEffect
@@ -645,14 +645,16 @@
 4d85e814f94949dae4dc6cb82bbd7d6bb24ffafda6ddb2eac928d2a4fc2e21ce android.hardware.cas@1.2::types
 66931c2506fbb5af61f20138cb05e0a09e7bf67d6964c231d27c648933bb33ec android.hardware.drm@1.3::ICryptoFactory
 994d08ab27d613022c258a9ec48cece7adf2a305e92df5d76ef923e2c6665f64 android.hardware.drm@1.3::IDrmFactory
-881aa8720fb1d69aa9843bfab69d810ab7654a61d2f5ab5e2626cbf240f24eaf android.hardware.dumpstate@1.1::types
-13b33f623521ded51a6c0f7ea5b77e97066d0aa1e38a83c2873f08ad67294f89 android.hardware.dumpstate@1.1::IDumpstateDevice
+446287268831f4ddfac4a51bb1c32ae1e48e47bccd535fccc2c4546d0e7c4013 android.hardware.dumpstate@1.1::types
+f284ffde7cadf5a1364b75ab313baf22401eeca289bdde2a2dc7a27ea4ab98d7 android.hardware.dumpstate@1.1::IDumpstateDevice
 769d346927a94fd40ee80a5a976d8d15cf022ef99c5900738f4a82f26c0ed229 android.hardware.gnss@2.1::types
-88371e0edf69a1f72bfc45ecb2335e9b145e87339d3eecc92664a1fb200213ba android.hardware.gnss@2.1::IGnss
-ba62e1e8993bfb9f27fa04816fa0f2241ae2d01edfa3d0c04182e2e5de80045c android.hardware.gnss@2.1::IGnssCallback
-ccdf3c0fb2c02a6d4dc57afb276c3497ae8172b80b00ebc0bf8a0238dd38b01d android.hardware.gnss@2.1::IGnssConfiguration
-5a125c49ca83629e22afc8c39e865509343bfa2c38f0baea9a186bbac103492d android.hardware.gnss@2.1::IGnssMeasurement
-d7bf37660a0946de9599dcbae997b077ee3e604fc2044534d40d3da04297a5d3 android.hardware.gnss@2.1::IGnssMeasurementCallback
+626db710bf917ecf551a0b0b1f25be10bf52758f43e0fc808b148b6aae2ef73e android.hardware.gnss@2.1::IGnss
+ba5ac712b2a656dc07c83ab4a7a2c2f3bee1bbcb752e8b8ffa9b672f3b5b0728 android.hardware.gnss@2.1::IGnssAntennaInfo
+0bc3ed97cbc3f6abc89c68f4e9f4d124f9f723431997dc88c2186cf4d2ad47ee android.hardware.gnss@2.1::IGnssAntennaInfoCallback
+50c5d009af76d65b3023a9d94ee519545e72cb7c59bc7166d768d6f00923774d android.hardware.gnss@2.1::IGnssCallback
+737d750017738f0753d13ba01a3310e0161f294b8ae80b3fd63eaa227e9d9c66 android.hardware.gnss@2.1::IGnssConfiguration
+7913a11206a577b12ade86a7cf3f95c2639cb514d086673f279bf99238c9917e android.hardware.gnss@2.1::IGnssMeasurement
+9999f2484f35ebfacdd433dfeae459f2a582334315959653ec8efde7699ec556 android.hardware.gnss@2.1::IGnssMeasurementCallback
 6670e7780803a8c696c6391fda5589a334b1b37dc7be9393792ed35035413633 android.hardware.gnss.measurement_corrections@1.1::IMeasurementCorrections
 a3f439b782a6a92aaf3c0250f3526e94e8bf8844c3d578f0815e21b12c431346 android.hardware.gnss.measurement_corrections@1.1::types
 ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
@@ -668,12 +670,12 @@
 df9c79c4fdde2821550c6d5c3d07f5ec0adfb1b702561ce543c906ddef698703 android.hardware.media.c2@1.1::IComponent
 a3eddd9bbdc87e8c22764070037dd1154f1cf006e6fba93364c4f85d4c134a19 android.hardware.media.c2@1.1::IComponentStore
 65c16331e57f6dd68b3971f06f78fe9e3209afb60630c31705aa355f9a52bf0d android.hardware.neuralnetworks@1.3::IBuffer
-9b41dd49e2dcc2ecb4243d03f8421d72494ada5cf2945bff88f0019eeca56923 android.hardware.neuralnetworks@1.3::IDevice
+9db064ee44268a876be0367ff771e618362d39ec603b6ecab17e1575725fcd87 android.hardware.neuralnetworks@1.3::IDevice
 4167dc3ad35e9cd0d2057d4868c7675ae2c3c9d05bbd614c1f5dccfa5fd68797 android.hardware.neuralnetworks@1.3::IExecutionCallback
 2fa3679ad7c94b5e88724adcd560c561041068a4ca565c63830e68101988746a android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
 237b23b126a66f3432658020fed78cdd06ba6297459436fe6bae0ba753370833 android.hardware.neuralnetworks@1.3::IPreparedModel
 0439a1fbbec7f16e5e4c653d85ac685d51bfafbae15b8f8cca530acdd7d6a8ce android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-3646950b10f7cacdafca13609b0e18496cea942f3bdfe920494661856eff48bb android.hardware.neuralnetworks@1.3::types
+2fabd246f985d94a0172dacefb0d6cf19e2aeb2d5f17752653988ef39570a52d android.hardware.neuralnetworks@1.3::types
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
 c67aaf26a7a40d14ea61e70e20afacbd0bb906df1704d585ac8599fbb69dd44b android.hardware.wifi.hostapd@1.2::IHostapd
 2b5a7ea572b736030c64a3b4043af244425477c4672301780fe15aba5ed393d9 android.hardware.wifi.hostapd@1.2::types
@@ -682,10 +684,10 @@
 def77c7db95d374f11a111bfc4ed60f92451303642a43276c4e291988fcee625 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 62cf050c593c1ec34b49178b5bdde72dd9b80d9bad3eb184e4f0cd564d28678c android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
-e1d34b83188a8ef3c507ec53c0ebcf714863c746da7f4a05460453f7c4c09389 android.hardware.radio@1.5::types
-8062d0a1a03594dd8b448adcf6f08856b5720f7e33f9b785a21d3ef74a4f211d android.hardware.radio@1.5::IRadio
+99f5c26b952271d1246c957e1d0271fa39445ee65cc93aa7c187834f98914a33 android.hardware.radio@1.5::types
+7fefa2cc5b3b3be10b5cff5c5dc195385f491d4bf23ca65f9c6b3c30c8753a33 android.hardware.radio@1.5::IRadio
 e96ae1c3a9c0689002ec2318e9c587f4f607c16a75a3cd38788b77eb91072021 android.hardware.radio@1.5::IRadioIndication
-7f2439b48bda2961c6d629d0415eee66d519142cf9537f05e9d285153c70ca85 android.hardware.radio@1.5::IRadioResponse
+829d3827eeb5a8f563e80fe627419b3231012fc02bc2e79782ec5e9ad9f799a4 android.hardware.radio@1.5::IRadioResponse
 dcc8872337f0135e81970e1d8d5fd7139160dc80e9be76f0ae05290fa7e472b8 android.hardware.radio.config@1.3::types
 a2977755bc5f1ef47f04b7f2400632efda6218e1515dba847da487145cfabc4f android.hardware.radio.config@1.3::IRadioConfig
 742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
diff --git a/dumpstate/1.1/IDumpstateDevice.hal b/dumpstate/1.1/IDumpstateDevice.hal
index 24831b3..502c460 100644
--- a/dumpstate/1.1/IDumpstateDevice.hal
+++ b/dumpstate/1.1/IDumpstateDevice.hal
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.hardware.dumpstate@1.1;
 
 import @1.0::IDumpstateDevice;
@@ -28,14 +29,19 @@
      * The 1.0 version of #dumpstateBoard(handle) should just delegate to this new method and pass
      * DumpstateMode::DEFAULT and a timeout of 30,000ms (30 seconds).
      *
+     * This method may still be called by the dumpstate routine even if getDeviceLoggingEnabled
+     * returns false. In this case, it must return DumpstateStatus::DEVICE_LOGGING_NOT_ENABLED.
+     *
      * @param h A native handle with one or two valid file descriptors. The first FD is for text
      *     output, the second (if present) is for binary output.
      * @param mode A mode value to restrict dumped content.
      * @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
      *     If execution runs longer than this, the IDumpstateDevice service may be killed and only
      *     partial information will be included in the report.
+     * @return status A DumpstateStatus value indicating the final result.
      */
-    dumpstateBoard_1_1(handle h, DumpstateMode mode, uint64_t timeoutMillis);
+    dumpstateBoard_1_1(handle h, DumpstateMode mode, uint64_t timeoutMillis)
+        generates (DumpstateStatus status);
 
     /**
      * Turns device vendor logging on or off.
@@ -46,8 +52,20 @@
      * memory/storage/battery impacts, calling this method on a user build should only be done after
      * user consent has been obtained, e.g. from a toggle in developer settings.
      *
+     * Even if device logging has been disabled, dumpstateBoard may still be called by the dumpstate
+     * routine. In this case, it must return DumpstateStatus::DEVICE_LOGGING_NOT_ENABLED.
+     *
      * @param enable Whether to enable or disable device vendor logging.
-     * @return success Whether or not the change took effect.
      */
-    setDeviceLoggingEnabled(bool enable) generates (bool success);
+    setDeviceLoggingEnabled(bool enable);
+
+    /**
+     * Queries the current state of device logging. Primarily for UI and informative purposes.
+     *
+     * Even if device logging has been disabled, dumpstateBoard may still be called by the dumpstate
+     * routine. In this case, it must return DumpstateStatus::DEVICE_LOGGING_NOT_ENABLED.
+     *
+     * @return enabled Whether or not vendor logging is currently enabled.
+     */
+    getDeviceLoggingEnabled() generates (bool enabled);
 };
diff --git a/dumpstate/1.1/types.hal b/dumpstate/1.1/types.hal
index a6f391a..f5cbade 100644
--- a/dumpstate/1.1/types.hal
+++ b/dumpstate/1.1/types.hal
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.hardware.dumpstate@1.1;
 
 /**
@@ -23,22 +24,18 @@
      * Takes a bug report without user interference.
      */
     FULL = 0,
-
     /**
      * Interactive bug report, i.e. triggered by the user.
      */
     INTERACTIVE = 1,
-
     /**
      * Remote bug report triggered by DevicePolicyManager, for example.
      */
     REMOTE = 2,
-
     /**
      * Bug report triggered on a wear device.
      */
     WEAR = 3,
-
     /**
      * Bug report limited to only connectivity info (cellular, wifi, and networking). Sometimes
      * called "telephony" in legacy contexts.
@@ -49,14 +46,34 @@
      * user application traffic.
      */
     CONNECTIVITY = 4,
-
     /**
      * Bug report limited to only wifi info.
      */
     WIFI = 5,
-
     /**
-     * Default mode.
+     * Default mode, essentially analogous to calling @1.0::IDumpstateDevice.dumpstateBoard(handle).
+     * This mode MUST be supported if the dumpstate HAL is implemented.
      */
-    DEFAULT = 6
+    DEFAULT = 6,
+};
+
+/**
+ * A simple return enum for use with dumpstateBoard_1_1.
+ */
+enum DumpstateStatus : uint32_t {
+    OK = 0,
+    /**
+     * Returned for cases where the device doesn't support the given DumpstateMode (e.g. a phone
+     * trying to use DumpstateMode::WEAR).
+     */
+    UNSUPPORTED_MODE = 1,
+    /**
+     * Returned for cases where an IllegalArgumentException is typically appropriate, e.g. missing
+     * file descriptors.
+     */
+    ILLEGAL_ARGUMENT = 2,
+    /**
+     * Returned when device logging is not enabled.
+     */
+    DEVICE_LOGGING_NOT_ENABLED = 3,
 };
diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
index 583efbf..089b039 100644
--- a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
+++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <functional>
 #include <vector>
 
 #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
@@ -34,21 +35,56 @@
 using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::dumpstate::V1_1::DumpstateMode;
+using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
 using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_1::toString;
 
 class DumpstateHidl1_1Test : public ::testing::TestWithParam<std::string> {
-  public:
-    virtual void SetUp() override {
+  protected:
+    virtual void SetUp() override { GetService(); }
+
+    void GetService() {
         dumpstate = IDumpstateDevice::getService(GetParam());
         ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance";
     }
 
+    void ToggleDeviceLogging(bool enable) {
+        Return<void> status = dumpstate->setDeviceLoggingEnabled(enable);
+        ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+        if (!dumpstate->ping().isOk()) {
+            ALOGW("IDumpstateDevice service appears to have exited lazily, attempting to get "
+                  "again");
+            GetService();
+        }
+
+        Return<bool> logging_enabled = dumpstate->getDeviceLoggingEnabled();
+        ASSERT_TRUE(logging_enabled.isOk())
+                << "Status should be ok: " << logging_enabled.description();
+        ASSERT_EQ(logging_enabled, enable)
+                << "Device logging should now be " << (enable ? "enabled" : "disabled");
+
+        if (!dumpstate->ping().isOk()) {
+            ALOGW("IDumpstateDevice service appears to have exited lazily, attempting to get "
+                  "again");
+            GetService();
+        }
+    }
+
+    void EnableDeviceLogging() { ToggleDeviceLogging(true); }
+
+    void DisableDeviceLogging() { ToggleDeviceLogging(false); }
+
     sp<IDumpstateDevice> dumpstate;
 };
 
 #define TEST_FOR_DUMPSTATE_MODE(name, body, mode) \
     TEST_P(DumpstateHidl1_1Test, name##_##mode) { body(DumpstateMode::mode); }
 
+// We use a macro to define individual test cases instead of hidl_enum_range<> because some HAL
+// implementations are lazy and may call exit() at the end of dumpstateBoard(), which would cause
+// DEAD_OBJECT errors after the first iteration. Separate cases re-get the service each time as part
+// of SetUp(), and also provide better separation of concerns when specific modes are problematic.
 #define TEST_FOR_ALL_DUMPSTATE_MODES(name, body)       \
     TEST_FOR_DUMPSTATE_MODE(name, body, FULL);         \
     TEST_FOR_DUMPSTATE_MODE(name, body, INTERACTIVE);  \
@@ -60,21 +96,51 @@
 
 constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000;  // 30 seconds
 
+// Will only execute additional_assertions when status == expected.
+void AssertStatusForMode(const DumpstateMode mode, const Return<DumpstateStatus>& status,
+                         const DumpstateStatus expected,
+                         std::function<void()> additional_assertions = nullptr) {
+    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
+                               << status.description();
+    if (mode == DumpstateMode::DEFAULT) {
+        ASSERT_EQ(expected, status) << "Required mode (DumpstateMode::" << toString(mode)
+                                    << "): status should be DumpstateStatus::" << toString(expected)
+                                    << ", but got DumpstateStatus::" << toString(status);
+    } else {
+        // The rest of the modes are optional to support, but they MUST return either the expected
+        // value or UNSUPPORTED_MODE.
+        ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
+                << "Optional mode (DumpstateMode::" << toString(mode)
+                << "): status should be DumpstateStatus::" << toString(expected)
+                << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
+                << toString(status);
+    }
+    if (status == expected && additional_assertions != nullptr) {
+        additional_assertions();
+    }
+}
+
 // Negative test: make sure dumpstateBoard() doesn't crash when passed a null pointer.
 TEST_FOR_ALL_DUMPSTATE_MODES(TestNullHandle, [this](DumpstateMode mode) {
-    Return<void> status = dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+    EnableDeviceLogging();
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+
+    AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
 });
 
 // Negative test: make sure dumpstateBoard() ignores a handle with no FD.
 TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithNoFd, [this](DumpstateMode mode) {
+    EnableDeviceLogging();
+
     native_handle_t* handle = native_handle_create(0, 0);
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
 
     native_handle_close(handle);
     native_handle_delete(handle);
@@ -82,6 +148,8 @@
 
 // Positive test: make sure dumpstateBoard() writes something to the FD.
 TEST_FOR_ALL_DUMPSTATE_MODES(TestOk, [this](DumpstateMode mode) {
+    EnableDeviceLogging();
+
     // Index 0 corresponds to the read end of the pipe; 1 to the write end.
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
@@ -90,12 +158,14 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
 
-    // Check that at least one byte was written
-    char buff;
-    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "dumped nothing";
+    AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds]() {
+        // Check that at least one byte was written.
+        char buff;
+        ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+    });
 
     native_handle_close(handle);
     native_handle_delete(handle);
@@ -103,6 +173,8 @@
 
 // Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
 TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithTwoFds, [this](DumpstateMode mode) {
+    EnableDeviceLogging();
+
     int fds1[2];
     int fds2[2];
     ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
@@ -113,8 +185,17 @@
     handle->data[0] = fds1[1];
     handle->data[1] = fds2[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+
+    AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds1, &fds2]() {
+        // Check that at least one byte was written to one of the FDs.
+        char buff;
+        size_t read1 = read(fds1[0], &buff, 1);
+        size_t read2 = read(fds2[0], &buff, 1);
+        // Sometimes read returns -1, so we can't just add them together and expect >= 1.
+        ASSERT_TRUE(read1 == 1 || read2 == 1) << "Dumped nothing";
+    });
 
     native_handle_close(handle);
     native_handle_delete(handle);
@@ -122,6 +203,8 @@
 
 // Make sure dumpstateBoard_1_1 actually validates its arguments.
 TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Negative) {
+    EnableDeviceLogging();
+
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
 
@@ -129,16 +212,21 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(-100),
-                                                        kDefaultTimeoutMillis);
-    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
-                                << status.description();
+    Return<DumpstateStatus> status = dumpstate->dumpstateBoard_1_1(
+            handle, static_cast<DumpstateMode>(-100), kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
+                               << status.description();
+    ASSERT_EQ(status, DumpstateStatus::ILLEGAL_ARGUMENT)
+            << "Should return DumpstateStatus::ILLEGAL_ARGUMENT for invalid mode param";
 
     native_handle_close(handle);
     native_handle_delete(handle);
 }
 
 TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Undefined) {
+    EnableDeviceLogging();
+
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
 
@@ -146,26 +234,84 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(9001),
-                                                        kDefaultTimeoutMillis);
-    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
-                                << status.description();
+    Return<DumpstateStatus> status = dumpstate->dumpstateBoard_1_1(
+            handle, static_cast<DumpstateMode>(9001), kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
+                               << status.description();
+    ASSERT_EQ(status, DumpstateStatus::ILLEGAL_ARGUMENT)
+            << "Should return DumpstateStatus::ILLEGAL_ARGUMENT for invalid mode param";
 
     native_handle_close(handle);
     native_handle_delete(handle);
 }
 
-// Make sure toggling device logging doesn't crash.
-TEST_P(DumpstateHidl1_1Test, TestEnableDeviceLogging) {
-    Return<bool> status = dumpstate->setDeviceLoggingEnabled(true);
+// Positive test: make sure dumpstateBoard() from 1.0 doesn't fail.
+TEST_P(DumpstateHidl1_1Test, Test1_0MethodOk) {
+    EnableDeviceLogging();
+
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<void> status = dumpstate->dumpstateBoard(handle);
 
     ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+    // Check that at least one byte was written.
+    char buff;
+    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
 }
 
-TEST_P(DumpstateHidl1_1Test, TestDisableDeviceLogging) {
-    Return<bool> status = dumpstate->setDeviceLoggingEnabled(false);
+// Make sure disabling device logging behaves correctly.
+TEST_FOR_ALL_DUMPSTATE_MODES(TestDeviceLoggingDisabled, [this](DumpstateMode mode) {
+    DisableDeviceLogging();
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+
+    AssertStatusForMode(mode, status, DumpstateStatus::DEVICE_LOGGING_NOT_ENABLED, [&fds]() {
+        // Check that nothing was written. Could return 0 or -1.
+        char buff;
+        ASSERT_NE(1, read(fds[0], &buff, 1)) << "Dumped something when device logging is disabled";
+    });
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+});
+
+// Double-enable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateHidl1_1Test, TestRepeatedEnable) {
+    EnableDeviceLogging();
+    EnableDeviceLogging();
+}
+
+// Double-disable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateHidl1_1Test, TestRepeatedDisable) {
+    DisableDeviceLogging();
+    DisableDeviceLogging();
+}
+
+// Toggling in short order is perfectly valid.
+TEST_P(DumpstateHidl1_1Test, TestRepeatedToggle) {
+    EnableDeviceLogging();
+    DisableDeviceLogging();
+    EnableDeviceLogging();
+    DisableDeviceLogging();
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/gnss/2.1/Android.bp b/gnss/2.1/Android.bp
index 7efc4a6..2122399 100644
--- a/gnss/2.1/Android.bp
+++ b/gnss/2.1/Android.bp
@@ -9,6 +9,8 @@
     srcs: [
         "types.hal",
         "IGnss.hal",
+        "IGnssAntennaInfo.hal",
+        "IGnssAntennaInfoCallback.hal",
         "IGnssCallback.hal",
         "IGnssMeasurement.hal",
         "IGnssMeasurementCallback.hal",
diff --git a/gnss/2.1/IGnss.hal b/gnss/2.1/IGnss.hal
index ce37647..e4da507 100644
--- a/gnss/2.1/IGnss.hal
+++ b/gnss/2.1/IGnss.hal
@@ -18,10 +18,10 @@
 
 import android.hardware.gnss.measurement_corrections@1.1::IMeasurementCorrections;
 import @2.0::IGnss;
-
 import IGnssCallback;
 import IGnssMeasurement;
 import IGnssConfiguration;
+import IGnssAntennaInfo;
 
 /**
  * Represents the standard GNSS (Global Navigation Satellite System) interface.
@@ -72,5 +72,15 @@
      *
      * @return measurementCorrectionsIface Handle to the IMeasurementCorrections interface.
      */
-     getExtensionMeasurementCorrections_1_1() generates (IMeasurementCorrections measurementCorrectionsIface);
-};
\ No newline at end of file
+    getExtensionMeasurementCorrections_1_1()
+        generates (IMeasurementCorrections measurementCorrectionsIface);
+
+    /**
+     * This method returns the IGnssAntennaInfo interface.
+     *
+     * This method must return non-null.
+     *
+     * @return gnssAntennaInfoIface Handle to the IGnssAntennaInfo interface.
+     */
+    getExtensionGnssAntennaInfo() generates (IGnssAntennaInfo gnssAntennaInfoIface);
+};
diff --git a/gnss/2.1/IGnssAntennaInfo.hal b/gnss/2.1/IGnssAntennaInfo.hal
new file mode 100644
index 0000000..f77d874
--- /dev/null
+++ b/gnss/2.1/IGnssAntennaInfo.hal
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss@2.1;
+
+import IGnssAntennaInfoCallback;
+
+/**
+ * Extended interface for GNSS antenna information support.
+ */
+interface IGnssAntennaInfo {
+    enum GnssAntennaInfoStatus : int32_t {
+        SUCCESS = 0,
+        ERROR_ALREADY_INIT = -100,
+        ERROR_GENERIC = -101,
+    };
+
+    /**
+     * Registers the callback routines with the HAL.
+     *
+     * @param callback Handle to the GnssAntennaInfo callback interface.
+     */
+    setCallback(IGnssAntennaInfoCallback callback) generates (GnssAntennaInfoStatus initRet);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to close(), the previously registered callbacks must be
+     * considered invalid by the HAL.
+     * If close() is invoked without a previous setCallback, this function must perform
+     * no work.
+     */
+    close();
+};
diff --git a/gnss/2.1/IGnssAntennaInfoCallback.hal b/gnss/2.1/IGnssAntennaInfoCallback.hal
new file mode 100644
index 0000000..883111e
--- /dev/null
+++ b/gnss/2.1/IGnssAntennaInfoCallback.hal
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss@2.1;
+
+/**
+ * The callback interface to report GNSS antenna information from the HAL.
+ */
+interface IGnssAntennaInfoCallback {
+    /**
+     * A row of doubles. This is used to represent a row in a 2D array, which are used to
+     * characterize the phase center variation corrections and signal gain corrections.
+     */
+    struct Row {
+        vec<double> row;
+    };
+
+    /**
+     * A point in 3D space, with associated uncertainty.
+     */
+    struct Coord {
+        double x;
+
+        double xUncertainty;
+
+        double y;
+
+        double yUncertainty;
+
+        double z;
+
+        double zUncertainty;
+    };
+
+    struct GnssAntennaInfo {
+        /**
+         * The carrier frequency in MHz.
+         */
+        double carrierFrequencyMHz;
+
+        /**
+         * Phase center offset (PCO) with associated 1-sigma uncertainty. PCO is defined with
+         * respect to the origin of the Android sensor coordinate system, e.g., center of primary
+         * screen for mobiles - see sensor or form factor documents for details.
+         */
+        Coord phaseCenterOffsetCoordinateMillimeters;
+
+        /**
+         * 2D vectors representing the phase center variation (PCV) corrections, in
+         * millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+         * (phi). The PCV correction is added to the phase measurement to obtain the
+         * corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        vec<Row> phaseCenterVariationCorrectionMillimeters;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+         * correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        vec<Row> phaseCenterVariationCorrectionUncertaintyMillimeters;
+
+        /**
+         * 2D vectors representing the signal gain corrections at regularly spaced
+         * azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+         * measured at the antenna feed point without considering the radio and receiver
+         * noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+         * antenna with the same total power. The signal gain correction is added the
+         * signal gain measurement to obtain the corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        vec<Row> signalGainCorrectionDbi;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+         * gain correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        vec<Row> signalGainCorrectionUncertaintyDbi;
+    };
+
+    /**
+     * Called when on connection, and on known-change to these values, such as upon a known
+     * GNSS RF antenna tuning change, or a foldable device state change.
+     *
+     * This is optional. It can never be called if the GNSS antenna information is not
+     * available.
+     */
+    gnssAntennaInfoCb(vec<GnssAntennaInfo> gnssAntennaInfos);
+};
diff --git a/gnss/2.1/IGnssCallback.hal b/gnss/2.1/IGnssCallback.hal
index da70742..f7b7477 100644
--- a/gnss/2.1/IGnssCallback.hal
+++ b/gnss/2.1/IGnssCallback.hal
@@ -24,8 +24,20 @@
  * the interfaces and passes a handle to the HAL.
  */
 interface IGnssCallback extends @2.0::IGnssCallback {
+    /**
+     * Flags for the gnssSetCapabilities callback.
+     */
+    @export(name = "", value_prefix = "GPS_CAPABILITY_")
+    enum Capabilities : @2.0::IGnssCallback.Capabilities {
+        /**
+         * GNSS supports measurement corrections
+         */
+        ANTENNA_INFO = 1 << 11,
+    };
 
-    /** Extends a GnssSvInfo, adding a basebandCN0DbHz. */
+    /**
+     * Extends a GnssSvInfo, adding a basebandCN0DbHz.
+     */
     struct GnssSvInfo {
         /**
          * GNSS satellite information for a single satellite and frequency.
diff --git a/gnss/2.1/IGnssConfiguration.hal b/gnss/2.1/IGnssConfiguration.hal
index 8360ba9..550f325 100644
--- a/gnss/2.1/IGnssConfiguration.hal
+++ b/gnss/2.1/IGnssConfiguration.hal
@@ -65,4 +65,4 @@
      * @return success Whether the HAL accepts and abides by the provided blacklist.
      */
     setBlacklist_2_1(vec<BlacklistedSource> blacklist) generates (bool success);
-};
\ No newline at end of file
+};
diff --git a/gnss/2.1/IGnssMeasurement.hal b/gnss/2.1/IGnssMeasurement.hal
index d2c76e6..49ba7eb 100644
--- a/gnss/2.1/IGnssMeasurement.hal
+++ b/gnss/2.1/IGnssMeasurement.hal
@@ -25,7 +25,6 @@
  * Extended interface for GNSS Measurements support.
  */
 interface IGnssMeasurement extends @2.0::IGnssMeasurement {
-
     /**
      * Initializes the interface and registers the callback routines with the HAL. After a
      * successful call to 'setCallback_2_1' the HAL must begin to provide updates at an average
@@ -47,5 +46,5 @@
      *     error code.
      */
     setCallback_2_1(IGnssMeasurementCallback callback, bool enableFullTracking)
-         generates (GnssMeasurementStatus initRet);
+        generates (GnssMeasurementStatus initRet);
 };
diff --git a/gnss/2.1/IGnssMeasurementCallback.hal b/gnss/2.1/IGnssMeasurementCallback.hal
index 0385abd..1aee272 100644
--- a/gnss/2.1/IGnssMeasurementCallback.hal
+++ b/gnss/2.1/IGnssMeasurementCallback.hal
@@ -21,36 +21,56 @@
 import @2.0::ElapsedRealtime;
 import GnssSignalType;
 
-/** The callback interface to report measurements from the HAL. */
+/**
+ * The callback interface to report measurements from the HAL.
+ */
 interface IGnssMeasurementCallback extends @2.0::IGnssMeasurementCallback {
-
     /**
      * Flags to indicate what fields in GnssMeasurement are valid.
      */
     enum GnssMeasurementFlags : uint32_t {
-        /** A valid 'snr' is stored in the data structure. */
-        HAS_SNR                           = 1 << 0,
-        /** A valid 'carrier frequency' is stored in the data structure. */
-        HAS_CARRIER_FREQUENCY             = 1 << 9,
-        /** A valid 'carrier cycles' is stored in the data structure. */
-        HAS_CARRIER_CYCLES                = 1 << 10,
-        /** A valid 'carrier phase' is stored in the data structure. */
-        HAS_CARRIER_PHASE                 = 1 << 11,
-        /** A valid 'carrier phase uncertainty' is stored in the data structure. */
-        HAS_CARRIER_PHASE_UNCERTAINTY     = 1 << 12,
-        /** A valid automatic gain control is stored in the data structure. */
-        HAS_AUTOMATIC_GAIN_CONTROL        = 1 << 13,
-        /** A valid receiver inter-signal bias is stored in the data structure. */
-        HAS_RECEIVER_ISB                  = 1 << 16,
-        /** A valid receiver inter-signal bias uncertainty is stored in the data structure. */
-        HAS_RECEIVER_ISB_UNCERTAINTY      = 1 << 17,
-        /** A valid satellite inter-signal bias is stored in the data structure. */
-        HAS_SATELLITE_ISB                 = 1 << 18,
-        /** A valid satellite inter-signal bias uncertainty is stored in the data structure. */
-        HAS_SATELLITE_ISB_UNCERTAINTY     = 1 << 19
+        /**
+         * A valid 'snr' is stored in the data structure.
+         */
+        HAS_SNR = 1 << 0,
+        /**
+         * A valid 'carrier frequency' is stored in the data structure.
+         */
+        HAS_CARRIER_FREQUENCY = 1 << 9,
+        /**
+         * A valid 'carrier cycles' is stored in the data structure.
+         */
+        HAS_CARRIER_CYCLES = 1 << 10,
+        /**
+         * A valid 'carrier phase' is stored in the data structure.
+         */
+        HAS_CARRIER_PHASE = 1 << 11,
+        /**
+         * A valid 'carrier phase uncertainty' is stored in the data structure.
+         */
+        HAS_CARRIER_PHASE_UNCERTAINTY = 1 << 12,
+        /**
+         * A valid automatic gain control is stored in the data structure.
+         */
+        HAS_AUTOMATIC_GAIN_CONTROL = 1 << 13,
+        /**
+         * A valid receiver inter-signal bias is stored in the data structure.
+         */
+        HAS_RECEIVER_ISB = 1 << 16,
+        /**
+         * A valid receiver inter-signal bias uncertainty is stored in the data structure.
+         */
+        HAS_RECEIVER_ISB_UNCERTAINTY = 1 << 17,
+        /**
+         * A valid satellite inter-signal bias is stored in the data structure.
+         */
+        HAS_SATELLITE_ISB = 1 << 18,
+        /**
+         * A valid satellite inter-signal bias uncertainty is stored in the data structure.
+         */
+        HAS_SATELLITE_ISB_UNCERTAINTY = 1 << 19,
     };
 
-
     /**
      * Extends a GNSS Measurement, adding basebandCN0DbHz, GnssMeasurementFlags,
      * receiverInterSignalBiasNs, receiverInterSignalBiasUncertaintyNs, satelliteInterSignalBiasNs
@@ -160,10 +180,14 @@
      * Complete set of GNSS Measurement data, same as 2.0 with additional fields in measurements.
      */
     struct GnssData {
-        /** The full set of satellite measurement observations. */
+        /**
+         * The full set of satellite measurement observations.
+         */
         vec<GnssMeasurement> measurements;
 
-        /** The GNSS clock time reading. */
+        /**
+         * The GNSS clock time reading.
+         */
         GnssClock clock;
 
         /**
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 1f1078e..c4dc8fd 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -22,6 +22,7 @@
     vintf_fragments: ["android.hardware.gnss@2.1-service.xml"],
     srcs: [
         "Gnss.cpp",
+        "GnssAntennaInfo.cpp",
         "GnssDebug.cpp",
         "GnssMeasurement.cpp",
         "GnssMeasurementCorrections.cpp",
diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp
index 679eb35..c1af103 100644
--- a/gnss/2.1/default/Gnss.cpp
+++ b/gnss/2.1/default/Gnss.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "Gnss"
 
 #include "Gnss.h"
+#include "GnssAntennaInfo.h"
 #include "GnssDebug.h"
 #include "GnssMeasurement.h"
 #include "GnssMeasurementCorrections.h"
@@ -334,9 +335,10 @@
 
     sGnssCallback_2_1 = callback;
 
-    using Capabilities = V2_0::IGnssCallback::Capabilities;
+    using Capabilities = V2_1::IGnssCallback::Capabilities;
     const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
-                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST |
+                              Capabilities::ANTENNA_INFO;
     auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_0(capabilities);
     if (!ret.isOk()) {
         ALOGE("%s: Unable to invoke callback", __func__);
@@ -374,6 +376,11 @@
     return new GnssMeasurementCorrections();
 }
 
+Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
+    ALOGD("Gnss::getExtensionGnssAntennaInfo");
+    return new GnssAntennaInfo();
+}
+
 void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
     std::unique_lock<std::mutex> lock(mMutex);
     // TODO(skz): update this to call 2_0 callback if non-null
diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h
index c47206a..bd5e6e8 100644
--- a/gnss/2.1/default/Gnss.h
+++ b/gnss/2.1/default/Gnss.h
@@ -22,6 +22,7 @@
 #include <atomic>
 #include <mutex>
 #include <thread>
+#include "GnssAntennaInfo.h"
 #include "GnssConfiguration.h"
 
 namespace android {
@@ -91,6 +92,7 @@
     Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
     Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
     getExtensionMeasurementCorrections_1_1() override;
+    Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
 
   private:
     void reportLocation(const V2_0::GnssLocation&) const;
diff --git a/gnss/2.1/default/GnssAntennaInfo.cpp b/gnss/2.1/default/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..d32a0af
--- /dev/null
+++ b/gnss/2.1/default/GnssAntennaInfo.cpp
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssAntennaInfo"
+
+#include "GnssAntennaInfo.h"
+#include "Utils.h"
+
+#include <log/log.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+sp<IGnssAntennaInfoCallback> GnssAntennaInfo::sCallback = nullptr;
+
+GnssAntennaInfo::GnssAntennaInfo() : mMinIntervalMillis(1000) {}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+    stop();
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+Return<GnssAntennaInfo::GnssAntennaInfoStatus> GnssAntennaInfo::setCallback(
+        const sp<IGnssAntennaInfoCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+
+    if (mIsActive) {
+        ALOGW("GnssAntennaInfo callback already set. Resetting the callback...");
+        stop();
+    }
+    start();
+
+    return GnssAntennaInfoStatus::SUCCESS;
+}
+
+Return<void> GnssAntennaInfo::close() {
+    ALOGD("close");
+    std::unique_lock<std::mutex> lock(mMutex);
+    stop();
+    sCallback = nullptr;
+    return Void();
+}
+
+// Private methods
+void GnssAntennaInfo::start() {
+    ALOGD("start");
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            if (sCallback != nullptr) {
+                auto antennaInfos = Utils::getMockAntennaInfos();
+                this->reportAntennaInfo(antennaInfos);
+            }
+
+            /** For mock implementation this is good. On real device, we should only report
+                antennaInfo at start and when there is a configuration change. **/
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMillis));
+        }
+    });
+}
+
+void GnssAntennaInfo::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GnssAntennaInfo::reportAntennaInfo(
+        const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (sCallback == nullptr) {
+        ALOGE("%s: No non-null callback", __func__);
+        return;
+    }
+
+    auto ret = sCallback->gnssAntennaInfoCb(antennaInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/2.1/default/GnssAntennaInfo.h b/gnss/2.1/default/GnssAntennaInfo.h
new file mode 100644
index 0000000..f4bfd24
--- /dev/null
+++ b/gnss/2.1/default/GnssAntennaInfo.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+
+#include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
+
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace V2_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssAntennaInfo : public IGnssAntennaInfo {
+    GnssAntennaInfo();
+    ~GnssAntennaInfo();
+
+    // Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+    Return<GnssAntennaInfoStatus> setCallback(
+            const sp<IGnssAntennaInfoCallback>& callback) override;
+    Return<void> close() override;
+
+  private:
+    void start();
+    void stop();
+    void reportAntennaInfo(
+            const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const;
+
+    static sp<IGnssAntennaInfoCallback> sCallback;
+    std::atomic<long> mMinIntervalMillis;
+    std::atomic<bool> mIsActive;
+    std::thread mThread;
+    mutable std::mutex mMutex;
+};
+
+}  // namespace implementation
+}  // namespace V2_1
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
\ No newline at end of file
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.cpp b/gnss/2.1/vts/functional/gnss_hal_test.cpp
index 93f89f5..83c4c3c 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test.cpp
@@ -262,4 +262,11 @@
     ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities);
     capabilities_cbq_.store(capabilities);
     return Void();
+}
+
+Return<void> GnssHalTest::GnssAntennaInfoCallback::gnssAntennaInfoCb(
+        const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
+    ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size());
+    antenna_info_cbq_.store(gnssAntennaInfos);
+    return Void();
 }
\ No newline at end of file
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.h b/gnss/2.1/vts/functional/gnss_hal_test.h
index b99cf23..3472edb 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test.h
+++ b/gnss/2.1/vts/functional/gnss_hal_test.h
@@ -31,6 +31,8 @@
 using android::hardware::gnss::V1_0::GnssLocationFlags;
 using android::hardware::gnss::V2_0::GnssConstellationType;
 using android::hardware::gnss::V2_1::IGnss;
+using android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
 
 using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
 using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
@@ -152,6 +154,20 @@
         Return<void> setCapabilitiesCb(uint32_t capabilities) override;
     };
 
+    /* Callback class for GnssAntennaInfo. */
+    class GnssAntennaInfoCallback : public IGnssAntennaInfoCallback {
+      public:
+        GnssCallbackEventQueue<hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>>
+                antenna_info_cbq_;
+
+        GnssAntennaInfoCallback() : antenna_info_cbq_("info"){};
+        virtual ~GnssAntennaInfoCallback() = default;
+
+        // Methods from V2_1::GnssAntennaInfoCallback follow.
+        Return<void> gnssAntennaInfoCb(
+                const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
+    };
+
     /*
      * SetUpGnssCallback:
      *   Set GnssCallback and verify the result.
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 9ac9436..7b054c0 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -139,7 +139,7 @@
             std::string codeType = lastMeasurement.clock.referenceSignalTypeForIsb.codeType;
 
             ASSERT_TRUE(referenceConstellation >= GnssConstellationType::UNKNOWN &&
-                        referenceConstellation >= GnssConstellationType::IRNSS);
+                        referenceConstellation <= GnssConstellationType::IRNSS);
             ASSERT_TRUE(carrierFrequencyHz > 0);
             ASSERT_TRUE(codeType != "");
 
@@ -154,6 +154,85 @@
 }
 
 /*
+ * TestGnssAntennaInfo:
+ * Sets a GnssAntennaInfoCallback, waits for report, and verifies
+ * 1. phaseCenterOffsetCoordinateMillimeters is valid
+ * 2. phaseCenterOffsetCoordinateUncertaintyMillimeters is valid.
+ * PhaseCenterVariationCorrections and SignalGainCorrections are optional.
+ */
+TEST_P(GnssHalTest, TestGnssAntennaInfo) {
+    const int kAntennaInfoTimeoutSeconds = 2;
+
+    auto gnssAntennaInfo = gnss_hal_->getExtensionGnssAntennaInfo();
+    ASSERT_TRUE(gnssAntennaInfo.isOk());
+
+    // Skip test if GnssAntennaInfo v2.1 is not supported
+    sp<IGnssAntennaInfo> iGnssAntennaInfo = gnssAntennaInfo;
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback_2_1::Capabilities::ANTENNA_INFO) ||
+        iGnssAntennaInfo == nullptr) {
+        ALOGD("GnssAntennaInfo v2.1 is not supported.");
+        return;
+    }
+
+    sp<GnssAntennaInfoCallback> callback = new GnssAntennaInfoCallback();
+    auto result = iGnssAntennaInfo->setCallback(callback);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_EQ(result, IGnssAntennaInfo::GnssAntennaInfoStatus::SUCCESS);
+
+    hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+    ASSERT_TRUE(callback->antenna_info_cbq_.retrieve(antennaInfos, kAntennaInfoTimeoutSeconds));
+    EXPECT_EQ(callback->antenna_info_cbq_.calledCount(), 1);
+    ASSERT_TRUE(antennaInfos.size() > 0);
+
+    for (auto antennaInfo : antennaInfos) {
+        // Remaining fields are optional
+        if (antennaInfo.phaseCenterVariationCorrectionMillimeters != NULL) {
+            int numRows = antennaInfo.phaseCenterVariationCorrectionMillimeters.size();
+            int numColumns = antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.phaseCenterVariationCorrectionMillimeters.size() ==
+                        antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.size());
+            ASSERT_TRUE(
+                    antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size() ==
+                    antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+        if (antennaInfo.signalGainCorrectionDbi != NULL) {
+            int numRows = antennaInfo.signalGainCorrectionDbi.size();
+            int numColumns = antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi.size());
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi[0].row.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.signalGainCorrectionDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.signalGainCorrectionUncertaintyDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+    }
+
+    iGnssAntennaInfo->close();
+}
+
+/*
  * TestGnssSvInfoFields:
  * Gets 1 location and a GnssSvInfo, and verifies
  * 1. basebandCN0DbHz is valid.
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 0cdc865..2e5b873 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -235,6 +235,58 @@
     return svInfo;
 }
 
+hidl_vec<GnssAntennaInfo> Utils::getMockAntennaInfos() {
+    GnssAntennaInfo mockAntennaInfo_1 = {
+            .carrierFrequencyMHz = 123412.12,
+            .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 1,
+                                                            .xUncertainty = 0.1,
+                                                            .y = 2,
+                                                            .yUncertainty = 0.1,
+                                                            .z = 3,
+                                                            .zUncertainty = 0.1},
+            .phaseCenterVariationCorrectionMillimeters =
+                    {
+                            Row{hidl_vec<double>{1, -1, 5, -2, 3, -1}},
+                            Row{hidl_vec<double>{-2, 3, 2, 0, 1, 2}},
+                            Row{hidl_vec<double>{1, 3, 2, -1, -3, 5}},
+                    },
+            .phaseCenterVariationCorrectionUncertaintyMillimeters =
+                    {
+                            Row{hidl_vec<double>{0.1, 0.2, 0.4, 0.1, 0.2, 0.3}},
+                            Row{hidl_vec<double>{0.3, 0.2, 0.3, 0.6, 0.1, 0.1}},
+                            Row{hidl_vec<double>{0.1, 0.1, 0.4, 0.2, 0.5, 0.3}},
+                    },
+            .signalGainCorrectionDbi =
+                    {
+                            Row{hidl_vec<double>{2, -3, 1, -3, 0, -4}},
+                            Row{hidl_vec<double>{1, 0, -4, 1, 3, -2}},
+                            Row{hidl_vec<double>{3, -2, 0, -2, 3, 0}},
+                    },
+            .signalGainCorrectionUncertaintyDbi =
+                    {
+                            Row{hidl_vec<double>{0.3, 0.1, 0.2, 0.6, 0.1, 0.3}},
+                            Row{hidl_vec<double>{0.1, 0.1, 0.5, 0.2, 0.3, 0.1}},
+                            Row{hidl_vec<double>{0.2, 0.4, 0.2, 0.1, 0.1, 0.2}},
+                    },
+    };
+
+    GnssAntennaInfo mockAntennaInfo_2 = {
+            .carrierFrequencyMHz = 532324.23,
+            .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 5,
+                                                            .xUncertainty = 0.1,
+                                                            .y = 6,
+                                                            .yUncertainty = 0.1,
+                                                            .z = 7,
+                                                            .zUncertainty = 0.1},
+    };
+
+    hidl_vec<GnssAntennaInfo> mockAntennaInfos = {
+            mockAntennaInfo_1,
+            mockAntennaInfo_2,
+    };
+    return mockAntennaInfos;
+}
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index e0c61a4..d9ad5a5 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -33,6 +33,9 @@
 using GnssSvInfoV1_0 = V1_0::IGnssCallback::GnssSvInfo;
 using GnssSvInfoV2_0 = V2_0::IGnssCallback::GnssSvInfo;
 using GnssSvInfoV2_1 = V2_1::IGnssCallback::GnssSvInfo;
+using GnssAntennaInfo = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::GnssAntennaInfo;
+using Row = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::Row;
+using Coord = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback::Coord;
 
 struct Utils {
     static GnssDataV2_0 getMockMeasurementV2_0();
@@ -46,6 +49,7 @@
     static GnssSvInfoV1_0 getMockSvInfoV1_0(int16_t svid, V1_0::GnssConstellationType type,
                                             float cN0DbHz, float elevationDegrees,
                                             float azimuthDegrees);
+    static hidl_vec<GnssAntennaInfo> getMockAntennaInfos();
 };
 
 }  // namespace common
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
index 168028d..ccb0690 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
@@ -107,19 +107,4 @@
      */
     long horizontalSubsampling;
     long verticalSubsampling;
-
-    /**
-     * Some buffer producers require extra padding to their output buffer; therefore the
-     * physical size of the native buffer will be larger than its logical size.
-     * The crop rectangle determines the offset and logical size of the buffer that should be
-     * read by consumers.
-     *
-     * The crop rectangle is measured in samples and is relative to the offset of the
-     * plane. Valid crop rectangles are within the boundaries of the plane:
-     * [0, 0, widthInSamples, heightInSamples].
-     *
-     * The default crop rectangle is a rectangle the same size as the plane:
-     * [0, 0, widthInSamples, heightInSamples].
-     */
-    Rect crop;
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index 7b46688..af6045e 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -260,6 +260,32 @@
     PLANE_LAYOUTS = 15,
 
     /**
+     * Can be used to get the crop of the buffer.
+     *
+     * Some buffer producers require extra padding to their output buffer; therefore the
+     * physical size of the native buffer will be larger than its logical size.
+     * The crop rectangle(s) determine the offset and logical size of the buffer that should be
+     * read by consumers.
+     *
+     * The crop is defined per plane. The crop(s) are represented by an array of
+     * android.hardware.graphics.common.Rects. The array must be the same length and in the same
+     * order as the array of PlaneLayouts. Eg. the first crop in the array is the crop for the
+     * first PlaneLayout in the PlaneLayout array.
+     *
+     * Each crop Rect is measured in samples and is relative to the offset of the plane. Valid crop
+     * rectangles are within the boundaries of the plane: [0, 0, widthInSamples, heightInSamples].
+     * The default crop rectangle of each plane is a rectangle the same size as the plane:
+     * [0, 0, widthInSamples, heightInSamples].
+     *
+     * When it is encoded into a byte stream, the total number of Rects is written using
+     * 8 bytes in little endian. It is followed by each Rect.
+     *
+     * To encode a Rect, write the following fields in this order each as 8 bytes in little endian:
+     * left, top, right and bottom.
+     */
+    CROP = 16,
+
+    /**
      * Can be used to get or set the dataspace of the buffer. The framework may attempt to set
      * this value.
      *
@@ -273,7 +299,7 @@
      * When it is encoded into a byte stream, it is first cast to a int32_t and then represented in
      * the byte stream by 4 bytes written in little endian.
      */
-    DATASPACE = 16,
+    DATASPACE = 17,
 
     /**
      * Can be used to get or set the BlendMode. The framework may attempt to set this value.
@@ -287,7 +313,7 @@
      * When it is encoded into a byte stream, it is first cast to a int32_t and then represented by
      * 4 bytes written in little endian.
      */
-    BLEND_MODE = 17,
+    BLEND_MODE = 18,
 
     /**
      * Can be used to get or set static HDR metadata specified by SMPTE ST 2086.
@@ -300,7 +326,7 @@
      * little endian. The ordering of float values follows the definition of Smpte2086 and XyColor.
      * If this is unset when encoded into a byte stream, the byte stream is empty.
      */
-    SMPTE2086 = 18,
+    SMPTE2086 = 19,
 
     /**
      * Can be used to get or set static HDR metadata specified by CTA 861.3.
@@ -313,7 +339,7 @@
      * little endian. The ordering of float values follows the definition of Cta861_3.
      * If this is unset when encoded into a byte stream, the byte stream is empty.
      */
-    CTA861_3 = 19,
+    CTA861_3 = 20,
 
     /**
      * Can be used to get or set dynamic HDR metadata specified by SMPTE ST 2094-40:2016.
@@ -326,5 +352,5 @@
      * using 8 bytes in little endian. It is followed by the uint8_t byte array.
      * If this is unset when encoded into a byte stream, the byte stream is empty.
      */
-    SMPTE2094_40 = 20,
+    SMPTE2094_40 = 21,
 }
diff --git a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
index 454a89c..0506f3a 100644
--- a/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
+++ b/graphics/composer/2.1/utils/vts/TestCommandReader.cpp
@@ -29,63 +29,68 @@
     mErrors.clear();
     mCompositionChanges.clear();
     while (!isEmpty()) {
-        IComposerClient::Command command;
+        int32_t command;
         uint16_t length;
         ASSERT_TRUE(beginCommand(&command, &length));
 
-        switch (command) {
-            case IComposerClient::Command::SELECT_DISPLAY:
-                ASSERT_EQ(2, length);
-                read64();  // display
-                break;
-            case IComposerClient::Command::SET_ERROR: {
-                ASSERT_EQ(2, length);
-                auto loc = read();
-                auto err = readSigned();
-                std::pair<uint32_t, uint32_t> error(loc, err);
-                mErrors.push_back(error);
-            } break;
-            case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
-                ASSERT_EQ(0, length % 3);
-                for (uint16_t count = 0; count < length / 3; ++count) {
-                    uint64_t layerId = read64();
-                    uint32_t composition = read();
-
-                    std::pair<uint64_t, uint32_t> compositionChange(layerId, composition);
-                    mCompositionChanges.push_back(compositionChange);
-                }
-                break;
-            case IComposerClient::Command::SET_DISPLAY_REQUESTS:
-                ASSERT_EQ(1, length % 3);
-                read();  // displayRequests, ignored for now
-                for (uint16_t count = 0; count < (length - 1) / 3; ++count) {
-                    read64();  // layer
-                    // silently eat requests to clear the client target, since we won't be testing
-                    // client composition anyway
-                    ASSERT_EQ(1u, read());
-                }
-                break;
-            case IComposerClient::Command::SET_PRESENT_FENCE:
-                ASSERT_EQ(1, length);
-                close(readFence());
-                break;
-            case IComposerClient::Command::SET_RELEASE_FENCES:
-                ASSERT_EQ(0, length % 3);
-                for (uint16_t count = 0; count < length / 3; ++count) {
-                    read64();
-                    close(readFence());
-                }
-                break;
-            default:
-                GTEST_FAIL() << "unexpected return command " << std::hex
-                             << static_cast<int>(command);
-                break;
-        }
+        parseSingleCommand(command, length);
 
         endCommand();
     }
 }
 
+void TestCommandReader::parseSingleCommand(int32_t commandRaw, uint16_t length) {
+    IComposerClient::Command command = static_cast<IComposerClient::Command>(commandRaw);
+
+    switch (command) {
+        case IComposerClient::Command::SELECT_DISPLAY:
+            ASSERT_EQ(2, length);
+            read64();  // display
+            break;
+        case IComposerClient::Command::SET_ERROR: {
+            ASSERT_EQ(2, length);
+            auto loc = read();
+            auto err = readSigned();
+            std::pair<uint32_t, uint32_t> error(loc, err);
+            mErrors.push_back(error);
+        } break;
+        case IComposerClient::Command::SET_CHANGED_COMPOSITION_TYPES:
+            ASSERT_EQ(0, length % 3);
+            for (uint16_t count = 0; count < length / 3; ++count) {
+                uint64_t layerId = read64();
+                uint32_t composition = read();
+
+                std::pair<uint64_t, uint32_t> compositionChange(layerId, composition);
+                mCompositionChanges.push_back(compositionChange);
+            }
+            break;
+        case IComposerClient::Command::SET_DISPLAY_REQUESTS:
+            ASSERT_EQ(1, length % 3);
+            read();  // displayRequests, ignored for now
+            for (uint16_t count = 0; count < (length - 1) / 3; ++count) {
+                read64();  // layer
+                // silently eat requests to clear the client target, since we won't be testing
+                // client composition anyway
+                ASSERT_EQ(1u, read());
+            }
+            break;
+        case IComposerClient::Command::SET_PRESENT_FENCE:
+            ASSERT_EQ(1, length);
+            close(readFence());
+            break;
+        case IComposerClient::Command::SET_RELEASE_FENCES:
+            ASSERT_EQ(0, length % 3);
+            for (uint16_t count = 0; count < length / 3; ++count) {
+                read64();
+                close(readFence());
+            }
+            break;
+        default:
+            GTEST_FAIL() << "unexpected return command " << std::hex << static_cast<int>(command);
+            break;
+    }
+}
+
 }  // namespace vts
 }  // namespace V2_1
 }  // namespace composer
diff --git a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
index c12debe..40d347a 100644
--- a/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
+++ b/graphics/composer/2.1/utils/vts/include/composer-vts/2.1/TestCommandReader.h
@@ -29,12 +29,16 @@
 // returned.
 class TestCommandReader : public CommandReaderBase {
    public:
-    // Parse all commands in the return command queue.  Call GTEST_FAIL() for
-    // unexpected errors or commands.
-    void parse();
+     virtual ~TestCommandReader() = default;
+     // Parse all commands in the return command queue.  Call GTEST_FAIL() for
+     // unexpected errors or commands.
+     void parse();
 
-    std::vector<std::pair<uint32_t, uint32_t>> mErrors;
-    std::vector<std::pair<uint64_t, uint32_t>> mCompositionChanges;
+     std::vector<std::pair<uint32_t, uint32_t>> mErrors;
+     std::vector<std::pair<uint64_t, uint32_t>> mCompositionChanges;
+
+   protected:
+     virtual void parseSingleCommand(int32_t commandRaw, uint16_t length);
 };
 
 }  // namespace vts
diff --git a/graphics/composer/2.4/utils/vts/Android.bp b/graphics/composer/2.4/utils/vts/Android.bp
index e42223d..fc13c2a 100644
--- a/graphics/composer/2.4/utils/vts/Android.bp
+++ b/graphics/composer/2.4/utils/vts/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "ComposerVts.cpp",
         "GraphicsComposerCallback.cpp",
+        "TestCommandReader.cpp",
     ],
     static_libs: [
         "android.hardware.graphics.composer@2.1",
@@ -33,6 +34,7 @@
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
         "android.hardware.graphics.composer@2.3-command-buffer",
+        "android.hardware.graphics.composer@2.4-command-buffer",
     ],
     cflags: [
         "-O0",
diff --git a/graphics/composer/2.4/utils/vts/ComposerVts.cpp b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
index c5f3b5e..b3f3374 100644
--- a/graphics/composer/2.4/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.4/utils/vts/ComposerVts.cpp
@@ -132,6 +132,38 @@
     return error;
 }
 
+void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) {
+    bool queueChanged = false;
+    uint32_t commandLength = 0;
+    hidl_vec<hidl_handle> commandHandles;
+    ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+    if (queueChanged) {
+        auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor());
+        ASSERT_EQ(V2_1::Error::NONE, ret);
+    }
+
+    mClient->executeCommands_2_3(
+            commandLength, commandHandles,
+            [&](const auto& tmpError, const auto& tmpOutQueueChanged, const auto& tmpOutLength,
+                const auto& tmpOutHandles) {
+                ASSERT_EQ(V2_1::Error::NONE, tmpError);
+
+                if (tmpOutQueueChanged) {
+                    mClient->getOutputCommandQueue(
+                            [&](const auto& tmpError, const auto& tmpDescriptor) {
+                                ASSERT_EQ(V2_3::Error::NONE, tmpError);
+                                reader->setMQDescriptor(tmpDescriptor);
+                            });
+                }
+
+                ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+                reader->parse();
+            });
+    reader->reset();
+    writer->reset();
+}
+
 }  // namespace vts
 }  // namespace V2_4
 }  // namespace composer
diff --git a/graphics/composer/2.4/utils/vts/TestCommandReader.cpp b/graphics/composer/2.4/utils/vts/TestCommandReader.cpp
new file mode 100644
index 0000000..a1ca628
--- /dev/null
+++ b/graphics/composer/2.4/utils/vts/TestCommandReader.cpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <composer-vts/2.4/TestCommandReader.h>
+
+#include <gtest/gtest.h>
+
+namespace android::hardware::graphics::composer::V2_4::vts {
+
+void TestCommandReader::parseSingleCommand(int32_t commandRaw, uint16_t length) {
+    IComposerClient::Command command = static_cast<IComposerClient::Command>(commandRaw);
+
+    switch (command) {
+        case IComposerClient::Command::SET_CLIENT_TARGET_PROPERTY:
+            ASSERT_EQ(2, length);
+            read();
+            close(readFence());
+            break;
+        default:
+            return android::hardware::graphics::composer::V2_1::vts::TestCommandReader::
+                    parseSingleCommand(commandRaw, length);
+    }
+}
+
+}  // namespace android::hardware::graphics::composer::V2_4::vts
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
index fd59eb9..28e17b4 100644
--- a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/ComposerVts.h
@@ -22,6 +22,7 @@
 #include <android/hardware/graphics/composer/2.4/IComposer.h>
 #include <android/hardware/graphics/composer/2.4/IComposerClient.h>
 #include <composer-vts/2.3/ComposerVts.h>
+#include <composer-vts/2.4/TestCommandReader.h>
 #include <utils/StrongPointer.h>
 
 namespace android {
@@ -92,6 +93,8 @@
 
     Error setContentType(Display display, IComposerClient::ContentType contentType);
 
+    void execute(TestCommandReader* reader, CommandWriterBase* writer);
+
     Error getLayerGenericMetadataKeys(
             std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys);
 
diff --git a/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/TestCommandReader.h b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/TestCommandReader.h
new file mode 100644
index 0000000..5736fa6
--- /dev/null
+++ b/graphics/composer/2.4/utils/vts/include/composer-vts/2.4/TestCommandReader.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
+#include <composer-vts/2.1/TestCommandReader.h>
+
+namespace android::hardware::graphics::composer::V2_4::vts {
+
+// A command parser that checks that no error nor unexpected commands are
+// returned.
+class TestCommandReader
+    : public android::hardware::graphics::composer::V2_1::vts::TestCommandReader {
+  protected:
+    void parseSingleCommand(int32_t commandRaw, uint16_t length) override;
+};
+
+}  // namespace android::hardware::graphics::composer::V2_4::vts
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index a7c3fd7..b6343d3 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -23,9 +23,9 @@
 #include <android-base/logging.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <composer-command-buffer/2.4/ComposerCommandBuffer.h>
-#include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.4/ComposerVts.h>
 #include <composer-vts/2.4/GraphicsComposerCallback.h>
+#include <composer-vts/2.4/TestCommandReader.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -77,7 +77,7 @@
         mComposerCallback->setVsyncAllowed(false);
 
         mWriter = std::make_unique<CommandWriterBase>(1024);
-        mReader = std::make_unique<V2_1::vts::TestCommandReader>();
+        mReader = std::make_unique<TestCommandReader>();
     }
 
     void TearDown() override {
@@ -153,7 +153,7 @@
     Display mPrimaryDisplay;
     Display mInvalidDisplayId;
     std::unique_ptr<CommandWriterBase> mWriter;
-    std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
+    std::unique_ptr<TestCommandReader> mReader;
 
   private:
     Display waitForFirstDisplay() {
@@ -184,7 +184,7 @@
                 mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT);
 
         mWriter = std::make_unique<CommandWriterBase>(1024);
-        mReader = std::make_unique<V2_1::vts::TestCommandReader>();
+        mReader = std::make_unique<TestCommandReader>();
     }
 
     void TearDown() override {
@@ -211,7 +211,7 @@
                                   int64_t newPeriodNanos);
 
     std::unique_ptr<CommandWriterBase> mWriter;
-    std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
+    std::unique_ptr<TestCommandReader> mReader;
     int32_t mDisplayWidth;
     int32_t mDisplayHeight;
 
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 2aad242..aa45e3b 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -151,11 +151,6 @@
                   planeLayout.totalSizeInBytes);
         EXPECT_EQ(1, planeLayout.horizontalSubsampling);
         EXPECT_EQ(1, planeLayout.verticalSubsampling);
-
-        EXPECT_EQ(0, planeLayout.crop.left);
-        EXPECT_EQ(0, planeLayout.crop.top);
-        EXPECT_EQ(planeLayout.widthInSamples, planeLayout.crop.right);
-        EXPECT_EQ(planeLayout.heightInSamples, planeLayout.crop.bottom);
     }
 
     void verifyBufferDump(const IMapper::BufferDump& bufferDump,
@@ -998,6 +993,22 @@
 }
 
 /**
+ * Test IMapper::get(Crop)
+ */
+TEST_P(GraphicsMapperHidlTest, GetCrop) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::RGBA_8888;
+    info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+    testGet(info, gralloc4::MetadataType_Crop,
+            [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::vector<aidl::android::hardware::graphics::common::Rect> crops;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops));
+                EXPECT_EQ(1, crops.size());
+            });
+}
+
+/**
  * Test IMapper::get(Dataspace)
  */
 TEST_P(GraphicsMapperHidlTest, GetDataspace) {
@@ -1104,6 +1115,8 @@
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
     ASSERT_EQ(0, vec.size());
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->get(bufferHandle, gralloc4::MetadataType_Crop, &vec));
+    ASSERT_EQ(0, vec.size());
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &vec));
     ASSERT_EQ(0, vec.size());
@@ -1362,10 +1375,6 @@
     planeLayoutA.totalSizeInBytes = planeLayoutA.strideInBytes * info.height;
     planeLayoutA.horizontalSubsampling = 1;
     planeLayoutA.verticalSubsampling = 1;
-    planeLayoutA.crop.left = 0;
-    planeLayoutA.crop.top = 0;
-    planeLayoutA.crop.right = info.width;
-    planeLayoutA.crop.bottom = info.height;
 
     component.type = gralloc4::PlaneLayoutComponentType_A;
     component.offsetInBits = 0;
@@ -1382,10 +1391,6 @@
     planeLayoutRGB.totalSizeInBytes = planeLayoutRGB.strideInBytes * info.height;
     planeLayoutRGB.horizontalSubsampling = 1;
     planeLayoutRGB.verticalSubsampling = 1;
-    planeLayoutRGB.crop.left = 0;
-    planeLayoutRGB.crop.top = 0;
-    planeLayoutRGB.crop.right = info.width;
-    planeLayoutRGB.crop.bottom = info.height;
 
     component.type = gralloc4::PlaneLayoutComponentType_R;
     planeLayoutRGB.components.push_back(component);
@@ -1423,11 +1428,6 @@
         EXPECT_EQ(planeLayout.horizontalSubsampling, realPlaneLayout.horizontalSubsampling);
         EXPECT_EQ(planeLayout.verticalSubsampling, realPlaneLayout.verticalSubsampling);
 
-        EXPECT_EQ(planeLayout.crop.left, realPlaneLayout.crop.left);
-        EXPECT_EQ(planeLayout.crop.top, realPlaneLayout.crop.top);
-        EXPECT_EQ(planeLayout.crop.right, realPlaneLayout.crop.right);
-        EXPECT_EQ(planeLayout.crop.bottom, realPlaneLayout.crop.bottom);
-
         ASSERT_EQ(planeLayout.components.size(), realPlaneLayout.components.size());
 
         for (int j = 0; j < realPlaneLayout.components.size(); j++) {
@@ -1443,6 +1443,26 @@
 }
 
 /**
+ * Test IMapper::set(Crop)
+ */
+TEST_P(GraphicsMapperHidlTest, SetCrop) {
+    std::vector<aidl::android::hardware::graphics::common::Rect> crops{{0, 0, 32, 32}};
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeCrop(crops, &vec));
+
+    testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Crop, vec,
+            [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+                std::vector<aidl::android::hardware::graphics::common::Rect> realCrops;
+                ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &realCrops));
+                ASSERT_EQ(1, realCrops.size());
+                ASSERT_EQ(crops.front().left, realCrops.front().left);
+                ASSERT_EQ(crops.front().top, realCrops.front().top);
+                ASSERT_EQ(crops.front().right, realCrops.front().right);
+                ASSERT_EQ(crops.front().bottom, realCrops.front().bottom);
+            });
+}
+
+/**
  * Test IMapper::set(Dataspace)
  */
 TEST_P(GraphicsMapperHidlTest, SetDataspace) {
@@ -1589,6 +1609,7 @@
               mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec));
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec));
+    ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Crop, vec));
     ASSERT_EQ(Error::BAD_BUFFER,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
     ASSERT_EQ(Error::BAD_BUFFER,
@@ -1607,16 +1628,48 @@
     const native_handle_t* bufferHandle = nullptr;
     ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
 
-    hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec));
-    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec));
-    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec));
-    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec));
+    uint64_t bufferId = 2;
+    hidl_vec<uint8_t> bufferIdVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeBufferId(bufferId, &bufferIdVec));
     ASSERT_EQ(Error::BAD_VALUE,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec));
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, bufferIdVec));
+
+    std::string name{"new name"};
+    hidl_vec<uint8_t> nameVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeName(name, &nameVec));
+    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, nameVec));
+
+    uint64_t width = 32;
+    hidl_vec<uint8_t> widthVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeWidth(width, &widthVec));
     ASSERT_EQ(Error::BAD_VALUE,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec));
-    ASSERT_EQ(Error::BAD_VALUE, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec));
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, widthVec));
+
+    uint64_t height = 32;
+    hidl_vec<uint8_t> heightVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeHeight(height, &heightVec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, heightVec));
+
+    uint64_t layerCount = 2;
+    hidl_vec<uint8_t> layerCountVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeLayerCount(layerCount, &layerCountVec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, layerCountVec));
+
+    hardware::graphics::common::V1_2::PixelFormat pixelFormatRequested = PixelFormat::BLOB;
+    hidl_vec<uint8_t> pixelFormatRequestedVec;
+    ASSERT_EQ(NO_ERROR,
+              gralloc4::encodePixelFormatRequested(pixelFormatRequested, &pixelFormatRequestedVec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested,
+                            pixelFormatRequestedVec));
+
+    uint64_t usage = 0;
+    hidl_vec<uint8_t> usageVec;
+    ASSERT_EQ(NO_ERROR, gralloc4::encodeUsage(usage, &usageVec));
+    ASSERT_EQ(Error::BAD_VALUE,
+              mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, usageVec));
 }
 
 /**
@@ -1628,19 +1681,9 @@
 
     hidl_vec<uint8_t> vec;
     ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_BufferId, vec));
-    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Name, vec));
-    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Width, vec));
-    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Height, vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_LayerCount, vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
-              mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatRequested, vec));
-    ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatFourCC, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_PixelFormatModifier, vec));
-    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Usage, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_AllocationSize, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
@@ -1653,6 +1696,7 @@
               mGralloc->set(bufferHandle, gralloc4::MetadataType_ChromaSiting, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_PlaneLayouts, vec));
+    ASSERT_EQ(Error::UNSUPPORTED, mGralloc->set(bufferHandle, gralloc4::MetadataType_Crop, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
               mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, vec));
     ASSERT_EQ(Error::UNSUPPORTED,
@@ -1867,6 +1911,23 @@
 }
 
 /**
+ * Test IMapper::getFromBufferDescriptorInfo(Crop)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCrop) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::RGBA_8888;
+    info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE,
+              mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec));
+
+    std::vector<aidl::android::hardware::graphics::common::Rect> crops;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops));
+    EXPECT_EQ(1, crops.size());
+}
+
+/**
  * Test IMapper::getFromBufferDescriptorInfo(Dataspace)
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) {
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index a30cdde..4c703c5 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -22,6 +22,9 @@
     shared_libs: [
         "libhidlbase",
     ],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+    test_config: "VtsHalHealthStorageV1_0TargetTest.config",
 }
-
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config
new file mode 100644
index 0000000..0cd1c11
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalHealthStorageV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalHealthStorageV1_0TargetTest->/data/local/tmp/VtsHalHealthStorageV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalHealthStorageV1_0TargetTest" />
+        <option name="native-test-timeout" value="3m" />
+    </test>
+</configuration>
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index e867120..993a105 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -3165,7 +3165,7 @@
      * * 8: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘height’ dimension.
      * * 9: An {@link OperandType::INT32} scalar, specifying the number of
-            groups.
+     *      groups.
      * * 10: An {@link OperandType::INT32} scalar, and has to be one of the
      *       {@link FusedActivationFunc} values. Specifies the activation to
      *       invoke on the result.
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 7886910..31a1a81 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -71,5 +71,5 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 8e82c53..58d3c4a 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -79,6 +79,18 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+// device name test
+TEST_P(NeuralnetworksHidlTest, GetDeviceNameTest) {
+    const std::string deviceName = getName(GetParam());
+    auto pos = deviceName.find('-');
+    EXPECT_NE(pos, std::string::npos);
+    // The separator should not be the first or last character.
+    EXPECT_NE(pos, 0);
+    EXPECT_NE(pos, deviceName.length() - 1);
+    // There should only be 1 separator.
+    EXPECT_EQ(std::string::npos, deviceName.find('-', pos + 1));
+}
+
 // device supported extensions test
 TEST_P(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
     Return<void> ret = kDevice->getSupportedExtensions(
diff --git a/neuralnetworks/1.3/IDevice.hal b/neuralnetworks/1.3/IDevice.hal
index 4931539..79f9c32 100644
--- a/neuralnetworks/1.3/IDevice.hal
+++ b/neuralnetworks/1.3/IDevice.hal
@@ -372,5 +372,5 @@
      */
     allocate(BufferDesc desc, vec<IPreparedModel> preparedModels, vec<BufferRole> inputRoles,
              vec<BufferRole> outputRoles)
-            generates (ErrorStatus status, IBuffer buffer, int32_t token);
+            generates (ErrorStatus status, IBuffer buffer, uint32_t token);
 };
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index ed577e4..530f984 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -22,9 +22,9 @@
 import @1.0::RequestArgument;
 import @1.2::Model.ExtensionNameAndPrefix;
 import @1.2::Model.ExtensionTypeEncoding;
+import @1.2::Operand.ExtraParams;
 import @1.2::OperandType;
 import @1.2::OperationType;
-import @1.2::SymmPerChannelQuantParams;
 
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -2556,6 +2556,30 @@
      *      A 3-D tensor of shape:
      *        If time-major: [max_time, batch_size, bw_output_size]
      *        If batch-major: [batch_size, max_time, bw_output_size]
+     * * 2: The forward activation state output.
+     *      A 2-D tensor of shape [batch_size, fw_output_size] containing an
+     *      activation state from the last time step in the sequence. This
+     *      output is optional and can be omitted. If this output is present
+     *      then outputs 3-5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 3: The forward cell state output.
+     *      A tensor of shape [batch_size, fw_cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted. If this output is present
+     *      then outputs 2, 4, 5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 4: The backward activation state output.
+     *      A 2-D tensor of shape [batch_size, bw_output_size] containing an
+     *      activation state from the last time step in the sequence. This
+     *      output is optional and can be omitted. If this output is present
+     *      then outputs 2, 3, 5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 5: The backward cell state output.
+     *      A tensor of shape [batch_size, bw_cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted. If this output is present
+     *      then outputs 2-4 must be present as well.
+     *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_LSTM = @1.2::OperationType:BIDIRECTIONAL_SEQUENCE_LSTM,
 
@@ -2673,6 +2697,18 @@
      *      (timeMajor). If it is set to true, then the shape is set to
      *      [maxTime, batchSize, bwNumUnits], otherwise the shape is set to
      *      [batchSize, maxTime, bwNumUnits].
+     * * 2: The forward hidden state output.
+     *      A 2-D tensor of shape [batchSize, fwNumUnits] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then output
+     *      3 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 3: The backward hidden state output.
+     *      A 2-D tensor of shape [batchSize, bwNumUnits] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then output
+     *      2 must be present as well.
+     *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_RNN = @1.2::OperationType:BIDIRECTIONAL_SEQUENCE_RNN,
 
@@ -3253,7 +3289,7 @@
      * * 8: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘height’ dimension.
      * * 9: An {@link OperandType::INT32} scalar, specifying the number of
-            groups.
+     *      groups.
      * * 10: An {@link OperandType::INT32} scalar, and has to be one of the
      *       {@link FusedActivationFunc} values. Specifies the activation to
      *       invoke on the result.
@@ -4656,6 +4692,15 @@
      *      A 3-D tensor of shape:
      *        If time-major: [max_time, batch_size, output_size]
      *        If batch-major: [batch_size, max_time, output_size]
+     * * 1: A tensor of shape [batch_size, output_size] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then
+     *      output #2 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 2: A tensor of shape [batch_size, cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted.
+     *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_LSTM = @1.2::OperationType:UNIDIRECTIONAL_SEQUENCE_LSTM,
 
@@ -4711,6 +4756,10 @@
      *      it is set to 1, then the output has a shape [maxTime, batchSize,
      *      numUnits], otherwise the output has a shape [batchSize, maxTime,
      *      numUnits].
+     * * 1: A tensor of shape [batchSize, numUnits] containing hidden state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted.
+     *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_RNN = @1.2::OperationType:UNIDIRECTIONAL_SEQUENCE_RNN,
 
@@ -5343,27 +5392,7 @@
     /**
      * Additional parameters specific to a particular operand type.
      */
-    safe_union ExtraParams {
-       /**
-        * No additional parameters.
-        */
-       Monostate none;
-
-       /**
-        * Symmetric per-channel quantization parameters.
-        *
-        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
-        */
-       SymmPerChannelQuantParams channelQuant;
-
-       /**
-        * Extension operand parameters.
-        *
-        * The framework treats this as an opaque data blob.
-        * The format is up to individual extensions.
-        */
-       vec<uint8_t> extension;
-    } extraParams;
+    @1.2::Operand.ExtraParams extraParams;
 };
 
 /**
@@ -5551,7 +5580,7 @@
          * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
          * and is specific to the IDevice object.
          */
-        int32_t token;
+        uint32_t token;
     };
 
     /**
@@ -5573,7 +5602,7 @@
      * Time point of the steady clock (as from std::chrono::steady_clock)
      * measured in nanoseconds.
      */
-    uint64_t nanoseconds;
+    uint64_t nanosecondsSinceEpoch;
 };
 
 /**
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index d4351ec..3d0d02d 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -24,9 +24,9 @@
 import @1.0::RequestArgument;
 import @1.2::Model.ExtensionNameAndPrefix;
 import @1.2::Model.ExtensionTypeEncoding;
+import @1.2::Operand.ExtraParams;
 import @1.2::OperandType;
 import @1.2::OperationType;
-import @1.2::SymmPerChannelQuantParams;
 
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -319,27 +319,7 @@
     /**
      * Additional parameters specific to a particular operand type.
      */
-    safe_union ExtraParams {
-       /**
-        * No additional parameters.
-        */
-       Monostate none;
-
-       /**
-        * Symmetric per-channel quantization parameters.
-        *
-        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
-        */
-       SymmPerChannelQuantParams channelQuant;
-
-       /**
-        * Extension operand parameters.
-        *
-        * The framework treats this as an opaque data blob.
-        * The format is up to individual extensions.
-        */
-       vec<uint8_t> extension;
-    } extraParams;
+    @1.2::Operand.ExtraParams extraParams;
 };
 
 /**
@@ -527,7 +507,7 @@
          * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
          * and is specific to the IDevice object.
          */
-        int32_t token;
+        uint32_t token;
     };
 
     /**
@@ -549,7 +529,7 @@
      * Time point of the steady clock (as from std::chrono::steady_clock)
      * measured in nanoseconds.
      */
-    uint64_t nanoseconds;
+    uint64_t nanosecondsSinceEpoch;
 };
 
 /**
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 8ea0b7e..82f34ff 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -122,15 +122,15 @@
     // Return {IBuffer object, token} if successful.
     // Return {nullptr, 0} if device memory is not supported.
     template <IOType ioType>
-    std::pair<sp<IBuffer>, int32_t> allocate(uint32_t index) {
-        std::pair<sp<IBuffer>, int32_t> buffer;
+    std::pair<sp<IBuffer>, uint32_t> allocate(uint32_t index) {
+        std::pair<sp<IBuffer>, uint32_t> buffer;
         allocateInternal<ioType>(index, &buffer);
         return buffer;
     }
 
   private:
     template <IOType ioType>
-    void allocateInternal(uint32_t index, std::pair<sp<IBuffer>, int32_t>* result) {
+    void allocateInternal(uint32_t index, std::pair<sp<IBuffer>, uint32_t>* result) {
         ASSERT_NE(result, nullptr);
 
         // Prepare arguments.
@@ -145,14 +145,14 @@
         // Allocate device memory.
         ErrorStatus status;
         sp<IBuffer> buffer;
-        int32_t token;
-        const auto ret = kDevice->allocate(
-                {}, {kPreparedModel}, inputRoles, outputRoles,
-                [&status, &buffer, &token](ErrorStatus error, const sp<IBuffer>& buf, int32_t tok) {
-                    status = error;
-                    buffer = buf;
-                    token = tok;
-                });
+        uint32_t token;
+        auto cb = [&status, &buffer, &token](ErrorStatus error, const sp<IBuffer>& buf,
+                                             uint32_t tok) {
+            status = error;
+            buffer = buf;
+            token = tok;
+        };
+        const auto ret = kDevice->allocate({}, {kPreparedModel}, inputRoles, outputRoles, cb);
 
         // Check allocation results.
         ASSERT_TRUE(ret.isOk());
@@ -217,7 +217,7 @@
             constRefSize += op.data.alignedSize();
         }
 
-        Operand::ExtraParams extraParams;
+        V1_2::Operand::ExtraParams extraParams;
         if (op.type == TestOperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
             extraParams.channelQuant(SymmPerChannelQuantParams{
                     .scales = op.channelQuant.scales, .channelDim = op.channelQuant.channelDim});
@@ -317,7 +317,7 @@
     // - [2+i, 2+i+o): Output device memories
     DeviceMemoryAllocator allocator(device, preparedModel, testModel);
     std::vector<sp<IBuffer>> buffers;
-    std::vector<int32_t> tokens;
+    std::vector<uint32_t> tokens;
 
     // Model inputs.
     hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
diff --git a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
index 62ffcda..2f1e05c 100644
--- a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
@@ -64,11 +64,11 @@
                     std::chrono::time_point_cast<std::chrono::nanoseconds>(currentTime);
             const uint64_t nanosecondsSinceEpoch =
                     currentTimeInNanoseconds.time_since_epoch().count();
-            deadline.nanoseconds(nanosecondsSinceEpoch);
+            deadline.nanosecondsSinceEpoch(nanosecondsSinceEpoch);
         } break;
         case DeadlineBoundType::UNLIMITED: {
             uint64_t unlimited = std::numeric_limits<uint64_t>::max();
-            deadline.nanoseconds(unlimited);
+            deadline.nanosecondsSinceEpoch(unlimited);
         } break;
     }
     return deadline;
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 1245432..b9ea430 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -50,7 +50,7 @@
 
     OptionalTimePoint deadline;
     if (testDeadline) {
-        deadline.nanoseconds(std::numeric_limits<uint64_t>::max());
+        deadline.nanosecondsSinceEpoch(std::numeric_limits<uint64_t>::max());
     }
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
@@ -527,9 +527,15 @@
                 }
             }
         }
-        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have either one or two
-        // outputs depending on their mergeOutputs parameter.
-        if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
+        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have
+        // either one, two, three or four outputs depending on their
+        // mergeOutputs parameter and if state outputs are provided.
+        // UNIDIRECTIONAL_SEQUENCE_LSTM and UNIDIRECTIONAL_SEQUENCE_RNN can have
+        // either one or three outputs depending on whether state outputs are
+        // provided.
+        if (operation.type == OperationType::UNIDIRECTIONAL_SEQUENCE_LSTM ||
+            operation.type == OperationType::UNIDIRECTIONAL_SEQUENCE_RNN ||
+            operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
             operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) {
             for (const size_t outOprand : operation.outputs) {
                 if (operand == outOprand) {
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 2fd9b64..2a4269f 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -61,7 +61,7 @@
 
     OptionalTimePoint deadline;
     if (testDeadline) {
-        deadline.nanoseconds(std::numeric_limits<uint64_t>::max());
+        deadline.nanosecondsSinceEpoch(std::numeric_limits<uint64_t>::max());
     }
 
     // asynchronous
@@ -142,16 +142,14 @@
     // dispatch
     {
         SCOPED_TRACE(message + " [executeFenced]");
-        Return<void> ret = preparedModel->executeFenced(
-                request, {}, MeasureTiming::NO, {}, {},
-                [](ErrorStatus error, const hidl_handle& handle,
-                   const sp<IFencedExecutionCallback>& callback) {
-                    if (error != ErrorStatus::DEVICE_UNAVAILABLE) {
-                        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
-                    }
-                    ASSERT_EQ(handle.getNativeHandle(), nullptr);
-                    ASSERT_EQ(callback, nullptr);
-                });
+        Return<void> ret =
+                preparedModel->executeFenced(request, {}, MeasureTiming::NO, deadline, {},
+                                             [](ErrorStatus error, const hidl_handle& handle,
+                                                const sp<IFencedExecutionCallback>& callback) {
+                                                 ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                                                 ASSERT_EQ(handle.getNativeHandle(), nullptr);
+                                                 ASSERT_EQ(callback, nullptr);
+                                             });
         ASSERT_TRUE(ret.isOk());
     }
 }
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 896ace6..9a87569 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -140,10 +140,7 @@
             request, {hidl_handle(nullptr)}, V1_2::MeasureTiming::NO, {}, {},
             [](ErrorStatus error, const hidl_handle& handle,
                const sp<IFencedExecutionCallback>& callback) {
-                // TODO: fix this once sample driver impl is merged.
-                if (error != ErrorStatus::DEVICE_UNAVAILABLE) {
-                    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
-                }
+                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
                 ASSERT_EQ(handle.getNativeHandle(), nullptr);
                 ASSERT_EQ(callback, nullptr);
             });
diff --git a/power/aidl/android/hardware/power/Mode.aidl b/power/aidl/android/hardware/power/Mode.aidl
index 9bb5b98..1792add 100644
--- a/power/aidl/android/hardware/power/Mode.aidl
+++ b/power/aidl/android/hardware/power/Mode.aidl
@@ -26,20 +26,20 @@
     DOUBLE_TAP_TO_WAKE,
 
     /**
-     * This mode indidates Low power mode is activated or not. Low power
+     * This mode indicates Low power mode is activated or not. Low power
      * mode is intended to save battery at the cost of performance.
      */
     LOW_POWER,
 
     /**
-     * This mode indidates Sustained Performance mode is activated or not.
+     * This mode indicates Sustained Performance mode is activated or not.
      * Sustained performance mode is intended to provide a consistent level of
      * performance for a prolonged amount of time.
      */
     SUSTAINED_PERFORMANCE,
 
     /**
-     * This mode indidates VR Mode is activated or not. VR mode is intended
+     * This mode indicates VR Mode is activated or not. VR mode is intended
      * to provide minimum guarantee for performance for the amount of time the
      * device can sustain it.
      */
@@ -76,6 +76,18 @@
      */
     INTERACTIVE,
 
+    /**
+     * This mode indicates the device is in device idle, externally known as doze.
+     * More details on:
+     * https://developer.android.com/training/monitoring-device-state/doze-standby
+     */
+    DEVICE_IDLE,
+
+    /**
+     * This mode indicates that display is either off or still on but is optimized
+     * for low-power.
+     */
+    DISPLAY_INACTIVE,
 
     /**
      * Below hints are currently not sent in Android framework but OEM might choose to
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index 2ec92e5..0b50436 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -69,6 +69,35 @@
             SignalThresholdInfo signalThresholdInfo, AccessNetwork accessNetwork);
 
     /**
+     * Sets the link capacity reporting criteria.
+     *
+     * The resulting reporting criteria are the AND of all the supplied criteria.
+     *
+     * Note: Reporting criteria must be individually set for each RAN. If unset, reporting criteria
+     * for that RAN are implementation-defined.
+     *
+     * Response callback is IRadioResponse.setLinkCapacityReportingCriteriaResponse_1_5().
+     *
+     * @param serial Serial number of request.
+     * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
+     *     disables hysteresis.
+     * @param hysteresisDlKbps An interval in kbps defining the required magnitude change between DL
+     *     reports. hysteresisDlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
+     * @param hysteresisUlKbps An interval in kbps defining the required magnitude change between UL
+     *     reports. hysteresisUlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
+     * @param thresholdsDownlinkKbps A vector of trigger thresholds in kbps for downlink reports. A
+     *     vector size of 0 disables the use of DL thresholds for reporting.
+     * @param thresholdsUplinkKbps A vector of trigger thresholds in kbps for uplink reports. A
+     *     vector size of 0 disables the use of UL thresholds for reporting.
+     * @param accessNetwork The type of network for which to apply these thresholds.
+     */
+    oneway setLinkCapacityReportingCriteria_1_5(int32_t serial, int32_t hysteresisMs,
+            int32_t hysteresisDlKbps, int32_t hysteresisUlKbps, vec<int32_t> thresholdsDownlinkKbps,
+            vec<int32_t> thresholdsUplinkKbps, AccessNetwork accessNetwork);
+
+    /**
      * Enable or disable UiccApplications on the SIM. If disabled:
      *  - Modem will not register on any network.
      *  - SIM must be PRESENT, and the IccId of the SIM must still be accessible.
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index aa8b526..e87cad2 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -20,6 +20,7 @@
 import @1.0::SendSmsResult;
 import @1.4::IRadioResponse;
 import @1.5::BarringInfo;
+import @1.5::CellIdentity;
 import @1.5::CellInfo;
 import @1.5::PersoSubstate;
 import @1.5::RegStateResult;
@@ -44,6 +45,17 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway setLinkCapacityReportingCriteriaResponse_1_5(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
      *   RadioError:SIM_ABSENT
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
@@ -165,6 +177,7 @@
 
     /**
      * @param info Response info struct containing response type, serial no. and error
+     * @param cellIdentity CellIdentity for the barring infos.
      * @param barringInfos a vector of barring info for all barring service types
      *
      * Valid errors returned:
@@ -173,7 +186,8 @@
      *   RadioError:INTERNAL_ERR
      *   RadioError:MODEM_ERR
      */
-    oneway getBarringInfoResponse(RadioResponseInfo info, vec<BarringInfo> barringInfos);
+    oneway getBarringInfoResponse(RadioResponseInfo info, CellIdentity cellIdentity,
+            vec<BarringInfo> barringInfos);
 
     /**
      * @param info Response info struct containing response type, serial no. and error
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index 448e5c8..4d3c2d5 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -156,7 +156,8 @@
 
 enum AccessNetwork : @1.4::AccessNetwork {
     /**
-     *  Next-Generation Radio Access Network (NGRAN)
+     * Next-Generation Radio Access Network (NGRAN).
+     * Note NGRAN is only for standalone mode. Non-standalone mode uses AccessNetwork EUTRAN.
      */
     NGRAN = 6,
 };
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 621825f..435bd23 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -310,6 +310,99 @@
 }
 
 /*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisDlKbps
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000,
+            5000,  // hysteresisDlKbps too big for thresholds delta
+            100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisUlKbps
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000, 500,
+            1000,  // hysteresisUlKbps too big for thresholds delta
+            {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() empty params
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_emptyParams) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 0, 0, 0, {}, {}, ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_emptyParams, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() for GERAN
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_Geran) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000, 500, 100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_Geran, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
  * Test IRadio.enableUiccApplications() for the response returned.
  * For SIM ABSENT case.
  */
@@ -1069,3 +1162,110 @@
                 CHECK_GENERAL_ERROR));
     }
 }
+
+/*
+ * Test IRadio.getBarringInfo() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, getBarringInfo) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->getBarringInfo(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ASSERT_TRUE(radioRsp_v1_5->barringInfos.size() > 0);
+
+    std::set<BarringInfo::ServiceType> reportedServices;
+
+    // validate that the service types are in range
+    for (const auto& info : radioRsp_v1_5->barringInfos) {
+        ASSERT_TRUE((info.serviceType >= BarringInfo::ServiceType::CS_SERVICE &&
+                     info.serviceType <= BarringInfo::ServiceType::SMS) ||
+                    (info.serviceType >= BarringInfo::ServiceType::OPERATOR_1 &&
+                     info.serviceType <= BarringInfo::ServiceType::OPERATOR_32));
+        reportedServices.insert(info.serviceType);
+
+        // Any type that is "conditional" must have sane values for conditional barring
+        // factor and time.
+        switch (info.barringType) {
+            case BarringInfo::BarringType::NONE:  // fall through
+            case BarringInfo::BarringType::UNCONDITIONAL:
+                break;
+            case BarringInfo::BarringType::CONDITIONAL: {
+                const int32_t barringFactor = info.barringTypeSpecificInfo.conditional().factor;
+                ASSERT_TRUE(barringFactor >= 0 && barringFactor <= 100);
+                ASSERT_TRUE(info.barringTypeSpecificInfo.conditional().timeSeconds > 0);
+                break;
+            }
+            default:
+                FAIL();
+        }
+    }
+
+    // Certain types of barring are relevant for certain RANs. Ensure that only the right
+    // types are reported. Note that no types are required, simply that for a given technology
+    // only certain types are valid. This is one way to sanity check that implementations are
+    // not providing information that they don't have.
+    static const std::set<BarringInfo::ServiceType> UTRA_SERVICES{
+            BarringInfo::ServiceType::CS_SERVICE, BarringInfo::ServiceType::PS_SERVICE,
+            BarringInfo::ServiceType::CS_VOICE,   BarringInfo::ServiceType::EMERGENCY,
+            BarringInfo::ServiceType::SMS,
+    };
+
+    static const std::set<BarringInfo::ServiceType> EUTRA_SERVICES{
+            BarringInfo::ServiceType::MO_SIGNALLING, BarringInfo::ServiceType::MO_DATA,
+            BarringInfo::ServiceType::CS_FALLBACK,   BarringInfo::ServiceType::MMTEL_VOICE,
+            BarringInfo::ServiceType::MMTEL_VIDEO,   BarringInfo::ServiceType::EMERGENCY,
+            BarringInfo::ServiceType::SMS,
+    };
+
+    static const std::set<BarringInfo::ServiceType> NGRA_SERVICES = {
+            BarringInfo::ServiceType::MO_SIGNALLING, BarringInfo::ServiceType::MO_DATA,
+            BarringInfo::ServiceType::CS_FALLBACK,   BarringInfo::ServiceType::MMTEL_VOICE,
+            BarringInfo::ServiceType::MMTEL_VIDEO,   BarringInfo::ServiceType::EMERGENCY,
+            BarringInfo::ServiceType::SMS,           BarringInfo::ServiceType::OPERATOR_1,
+            BarringInfo::ServiceType::OPERATOR_2,    BarringInfo::ServiceType::OPERATOR_3,
+            BarringInfo::ServiceType::OPERATOR_4,    BarringInfo::ServiceType::OPERATOR_5,
+            BarringInfo::ServiceType::OPERATOR_6,    BarringInfo::ServiceType::OPERATOR_7,
+            BarringInfo::ServiceType::OPERATOR_8,    BarringInfo::ServiceType::OPERATOR_9,
+            BarringInfo::ServiceType::OPERATOR_10,   BarringInfo::ServiceType::OPERATOR_11,
+            BarringInfo::ServiceType::OPERATOR_12,   BarringInfo::ServiceType::OPERATOR_13,
+            BarringInfo::ServiceType::OPERATOR_14,   BarringInfo::ServiceType::OPERATOR_15,
+            BarringInfo::ServiceType::OPERATOR_16,   BarringInfo::ServiceType::OPERATOR_17,
+            BarringInfo::ServiceType::OPERATOR_18,   BarringInfo::ServiceType::OPERATOR_19,
+            BarringInfo::ServiceType::OPERATOR_20,   BarringInfo::ServiceType::OPERATOR_21,
+            BarringInfo::ServiceType::OPERATOR_22,   BarringInfo::ServiceType::OPERATOR_23,
+            BarringInfo::ServiceType::OPERATOR_24,   BarringInfo::ServiceType::OPERATOR_25,
+            BarringInfo::ServiceType::OPERATOR_26,   BarringInfo::ServiceType::OPERATOR_27,
+            BarringInfo::ServiceType::OPERATOR_28,   BarringInfo::ServiceType::OPERATOR_29,
+            BarringInfo::ServiceType::OPERATOR_30,   BarringInfo::ServiceType::OPERATOR_31,
+    };
+
+    const std::set<BarringInfo::ServiceType>* compareTo = nullptr;
+
+    switch (radioRsp_v1_5->barringCellIdentity.getDiscriminator()) {
+        case android::hardware::radio::V1_5::CellIdentity::hidl_discriminator::wcdma:
+            // fall through
+        case android::hardware::radio::V1_5::CellIdentity::hidl_discriminator::tdscdma:
+            compareTo = &UTRA_SERVICES;
+            break;
+        case android::hardware::radio::V1_5::CellIdentity::hidl_discriminator::lte:
+            compareTo = &EUTRA_SERVICES;
+            break;
+        case android::hardware::radio::V1_5::CellIdentity::hidl_discriminator::nr:
+            compareTo = &NGRA_SERVICES;
+            break;
+
+        case android::hardware::radio::V1_5::CellIdentity::hidl_discriminator::cdma:
+            // fall through
+        default:
+            FAIL();
+            break;
+    }
+
+    std::set<BarringInfo::ServiceType> diff;
+
+    std::set_difference(reportedServices.begin(), reportedServices.end(), compareTo->begin(),
+                        compareTo->end(), std::inserter(diff, diff.begin()));
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index ce7b1ab..01cf40a 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -86,6 +86,10 @@
     // Whether Uicc applications are enabled or not.
     bool areUiccApplicationsEnabled;
 
+    // Barring Info Response
+    ::android::hardware::radio::V1_5::CellIdentity barringCellIdentity;
+    ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos;
+
     RadioResponse_v1_5(RadioHidlTest_v1_5& parent_v1_5);
     virtual ~RadioResponse_v1_5() = default;
 
@@ -531,6 +535,8 @@
     /* 1.5 Api */
     Return<void> setSignalStrengthReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
 
+    Return<void> setLinkCapacityReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
     Return<void> enableUiccApplicationsResponse(const RadioResponseInfo& info);
 
     Return<void> areUiccApplicationsEnabledResponse(const RadioResponseInfo& info, bool enabled);
@@ -556,6 +562,7 @@
 
     Return<void> getBarringInfoResponse(
             const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
             const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
                     barringInfos);
 
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 26401eb..e4f9ce8 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -894,6 +894,13 @@
     return Void();
 }
 
+Return<void> RadioResponse_v1_5::setLinkCapacityReportingCriteriaResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
 Return<void> RadioResponse_v1_5::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
     rspInfo = info;
     parent_v1_5.notify(info.serial);
@@ -963,8 +970,11 @@
 
 Return<void> RadioResponse_v1_5::getBarringInfoResponse(
         const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
         const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
-        /*barringInfos*/) {
+                barringInfos) {
+    this->barringCellIdentity = cellIdentity;
+    this->barringInfos = barringInfos;
     rspInfo = info;
     parent_v1_5.notify(info.serial);
     return Void();
diff --git a/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd b/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
new file mode 100644
index 0000000..45c01c1
--- /dev/null
+++ b/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfig.xsd
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<xs:schema version="1.0"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List of the Tuner Resource Manager client use case priority hint. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="config">
+        <xs:sequence>
+            <xs:element name="useCaseDefault" type="useCaseDefault" minOccurs="1" maxOccurs="1"/>
+            <xs:element name="useCasePreDefined" type="useCasePreDefined" minOccurs="0" maxOccurs="5"/>
+            <xs:element name="useCaseVendor" type="useCaseVendor" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="version" type="version"/>
+    </xs:complexType>
+
+    <xs:complexType name="useCaseDefault">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                useCaseDefault section:
+                Default value for predefined use cases priority hint.
+                    "fgPriority": priority when the use case is in foreground.
+                    "bgPriority": priority when the use case is in background.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="fgPriority" type="priority"/>
+        <xs:attribute name="bgPriority" type="priority"/>
+    </xs:complexType>
+
+    <xs:complexType name="useCasePreDefined">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                useCasePreDefined section:
+                A list of predefined use cases and their foreground/background priority hint.
+                Each use case has the following attributes:
+                    "type": type of the use case. Pre-defined use cases start with "USE_CASE_"
+                            and have been predefined in "predefinedUseCaseType".
+                    "fgPriority": priority when the use case is in foreground.
+                    "bgPriority": priority when the use case is in background.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="type" type="predefinedUseCaseType"/>
+        <xs:attribute name="fgPriority" type="priority"/>
+        <xs:attribute name="bgPriority" type="priority"/>
+    </xs:complexType>
+
+    <xs:complexType name="useCaseVendor">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                useCaseVendor section:
+                A list of vendor defined use cases and their foreground/background priority hint.
+                Each use case has the following attributes:
+                    "type": type of the use case. Vendor defined use cases start with "VENDOR_USE_CASE_".
+                    "fgPriority": priority when the use case is in foreground.
+                    "bgPriority": priority when the use case is in background.
+                    "id": Vendor defined use case must have an id greater than 1000 to be associated with.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="type" type="vendorUseCaseType"/>
+        <xs:attribute name="id" type="id"/>
+        <xs:attribute name="fgPriority" type="priority"/>
+        <xs:attribute name="bgPriority" type="priority"/>
+    </xs:complexType>
+
+    <xs:simpleType name="predefinedUseCaseType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="USE_CASE_RECORD"/>
+            <xs:enumeration value="USE_CASE_LIVE"/>
+            <xs:enumeration value="USE_CASE_PLAYBACK"/>
+            <xs:enumeration value="USE_CASE_SCAN"/>
+            <xs:enumeration value="USE_CASE_BACKGROUND"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="vendorUseCaseType">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="VENDOR_USE_CASE_[_A-Z0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="priority">
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="1000"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="id">
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="1001"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:element name="config" type="config"/>
+</xs:schema>
diff --git a/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml b/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
new file mode 100644
index 0000000..938faeb
--- /dev/null
+++ b/tv/tuner/1.0/config/tunerResourceManagerUseCaseConfigSample.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright 2020 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<!-- A sample Tuner Resource Manager use case priority configuration xml -->
+<config version="1.0" xmlns:xi="http://www.w3.org/2001/XMLSchema">
+    <!-- useCaseDefault section:
+        Default value for predefined use cases priority hint.
+            "fgPriority": priority when the use case is in foreground. Value range [0-1000].
+            "bgPriority": priority when the use case is in background. Value range [0-1000].
+    -->
+    <useCaseDefault fgPriority="150" bgPriority="50"/>
+    <!-- useCasePreDefined section:
+        A list of predefined use cases and their foreground/background priority hint.
+        Each use case has the following attributes:
+            "type": type of the use case. Pre-defined use cases start with "USE_CASE_"
+                    and could only use the types defined in "predefinedUseCaseType" in xsd.
+            "fgPriority": priority when the use case is in foreground. Value range [0-1000].
+            "bgPriority": priority when the use case is in background. Value range [0-1000].
+    -->
+    <useCasePreDefined type="USE_CASE_RECORD" fgPriority="600" bgPriority="500"/>
+    <useCasePreDefined type="USE_CASE_LIVE" fgPriority="490" bgPriority="400"/>
+    <useCasePreDefined type="USE_CASE_PLAYBACK" fgPriority="480" bgPriority="300"/>
+    <useCasePreDefined type="USE_CASE_SCAN" fgPriority="450" bgPriority="200"/>
+    <useCasePreDefined type="USE_CASE_BACKGROUND" fgPriority="180" bgPriority="100"/>
+    <!-- useCaseVendor section:
+        A list of vendor defined use cases and their foreground/background priority hint.
+        Each use case has the following attributes:
+            "type": type of the use case. Vendor defined use cases start with "VENDOR_USE_CASE_".
+            "fgPriority": priority when the use case is in foreground. Value range [0-1000].
+            "bgPriority": priority when the use case is in background. Value range [0-1000].
+            "id": Vendor defined use case must have an id greater than 1000 to be associated with.
+    -->
+    <useCaseVendor type="VENDOR_USE_CASE_SPECIAL_1" id="1001" fgPriority="300" bgPriority="80"/>
+    <useCaseVendor type="VENDOR_USE_CASE_SPECIAL_2" id="1002" fgPriority="200" bgPriority="40"/>
+</config>
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 1e07edd..dd2f8a6 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -90,11 +90,66 @@
     return Result::SUCCESS;
 }
 
-Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& /* statusTypes */,
+Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
                                  getStatus_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
     vector<FrontendStatus> statuses;
+    for (int i = 0; i < statusTypes.size(); i++) {
+        FrontendStatusType type = statusTypes[i];
+        FrontendStatus status;
+        // assign randomly selected values for testing.
+        switch (type) {
+            case FrontendStatusType::DEMOD_LOCK: {
+                status.isDemodLocked(true);
+                break;
+            }
+            case FrontendStatusType::SNR: {
+                status.snr(221);
+                break;
+            }
+            case FrontendStatusType::FEC: {
+                status.innerFec(FrontendInnerFec::FEC_2_9);  // value = 1 << 7
+                break;
+            }
+            case FrontendStatusType::MODULATION: {
+                FrontendModulationStatus modulationStatus;
+                modulationStatus.isdbt(FrontendIsdbtModulation::MOD_16QAM);  // value = 1 << 3
+                status.modulation(modulationStatus);
+                break;
+            }
+            case FrontendStatusType::PLP_ID: {
+                status.plpId(101);  // type uint8_t
+                break;
+            }
+            case FrontendStatusType::LAYER_ERROR: {
+                vector<bool> v = {false, true, true};
+                status.isLayerError(v);
+                break;
+            }
+            case FrontendStatusType::ATSC3_PLP_INFO: {
+                vector<FrontendStatusAtsc3PlpInfo> v;
+                FrontendStatusAtsc3PlpInfo info1{
+                        .plpId = 3,
+                        .isLocked = false,
+                        .uec = 313,
+                };
+                FrontendStatusAtsc3PlpInfo info2{
+                        .plpId = 5,
+                        .isLocked = true,
+                        .uec = 515,
+                };
+                v.push_back(info1);
+                v.push_back(info2);
+                status.plpInfo(v);
+                break;
+            }
+            default: {
+                continue;
+            }
+        }
+        statuses.push_back(status);
+    }
     _hidl_cb(Result::SUCCESS, statuses);
 
     return Void();
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index c6017f0..4fd3355 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -109,7 +109,37 @@
 Return<void> Tuner::getFrontendInfo(FrontendId /* frontendId */, getFrontendInfo_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    FrontendInfo info;
+    vector<FrontendStatusType> statusCaps = {
+            FrontendStatusType::DEMOD_LOCK,
+            FrontendStatusType::SNR,
+            FrontendStatusType::FEC,
+            FrontendStatusType::MODULATION,
+            FrontendStatusType::PLP_ID,
+            FrontendStatusType::LAYER_ERROR,
+            FrontendStatusType::ATSC3_PLP_INFO,
+    };
+    FrontendInfo::FrontendCapabilities frontendCaps;
+    FrontendIsdbtCapabilities isdbtCaps{
+            .modeCap = FrontendIsdbtMode::MODE_1 | FrontendIsdbtMode::MODE_2,
+            .bandwidthCap = (unsigned int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
+            .modulationCap = (unsigned int)FrontendIsdbtModulation::MOD_16QAM,
+            // ISDBT shares coderate and guard interval with DVBT
+            .coderateCap = FrontendDvbtCoderate::CODERATE_4_5 | FrontendDvbtCoderate::CODERATE_6_7,
+            .guardIntervalCap = (unsigned int)FrontendDvbtGuardInterval::INTERVAL_1_128,
+    };
+    frontendCaps.isdbtCaps(isdbtCaps);
+    // assign randomly selected values for testing.
+    FrontendInfo info{
+            .type = FrontendType::ISDBT,
+            .minFrequency = 139,
+            .maxFrequency = 1139,
+            .minSymbolRate = 45,
+            .maxSymbolRate = 1145,
+            .acquireRange = 30,
+            .exclusiveGroupId = 57,
+            .statusCaps = statusCaps,
+            .frontendCaps = frontendCaps,
+    };
 
     _hidl_cb(Result::SUCCESS, info);
     return Void();
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
index 2eaab36..e4874f4 100644
--- a/tv/tuner/1.0/types.hal
+++ b/tv/tuner/1.0/types.hal
@@ -1425,18 +1425,6 @@
      */
     LAYER_ERROR,
     /**
-     * CN value by VBER.
-     */
-    VBER_CN,
-    /**
-     * CN value by LBER.
-     */
-    LBER_CN,
-    /**
-     * CN value by XER.
-     */
-    XER_CN,
-    /**
      * Moduration Error Ratio.
      */
     MER,
@@ -1559,21 +1547,6 @@
     vec<bool> isLayerError;
 
     /**
-     * CN value by VBER measured by 0.001 dB
-     */
-    int32_t vberCn;
-
-    /**
-     * CN value by LBER measured by 0.001 dB
-     */
-    int32_t lberCn;
-
-    /**
-     * CN value by XER measured by 0.001 dB
-     */
-    int32_t xerCn;
-
-    /**
      * MER value measured by 0.001 dB
      */
     int32_t mer;
diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp
index 9781074..22dec84 100644
--- a/wifi/supplicant/1.2/vts/functional/Android.bp
+++ b/wifi/supplicant/1.2/vts/functional/Android.bp
@@ -68,7 +68,7 @@
     name: "VtsHalWifiSupplicantP2pV1_2TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "VtsHalWifiSupplicantV1_2TargetTest.cpp",
+        "VtsHalWifiSupplicantP2pV1_2TargetTest.cpp",
         "supplicant_p2p_iface_hidl_test.cpp",
     ],
     static_libs: [
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
new file mode 100644
index 0000000..22bf1db
--- /dev/null
+++ b/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsCoreUtil.h>
+#include "supplicant_hidl_test_utils.h"
+
+// TODO(b/143892896): Remove this line after wifi_hidl_test_utils.cpp is
+// updated.
+WifiSupplicantHidlEnvironment* gEnv = nullptr;
+
+int main(int argc, char** argv) {
+    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
+        return 0;
+
+    ::testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 93eabd6..6be24bc 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -56,6 +56,8 @@
         supplicant_ =
             getSupplicant_1_3(supplicant_v1_3_instance_name_, isP2pOn_);
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
+        sta_iface_ = getSupplicantStaIface_1_3(supplicant_);
+        ASSERT_NE(nullptr, sta_iface_.get());
         sta_network_ = createSupplicantStaNetwork_1_3(supplicant_);
         ASSERT_NE(sta_network_.get(), nullptr);
     }