Merge "AudioMetadata: Add documentation" into rvc-dev
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 872b35b..a4fd641 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -15,10 +15,12 @@
 cc_defaults {
     name: "vhal_v2_0_defaults",
     shared_libs: [
+        "libbinder_ndk",
         "libhidlbase",
         "liblog",
         "libutils",
         "android.hardware.automotive.vehicle@2.0",
+        "carwatchdog_aidl_interface-ndk_platform",
     ],
     cflags: [
         "-Wall",
@@ -46,6 +48,7 @@
         "common/src/VehiclePropertyStore.cpp",
         "common/src/VehicleUtils.cpp",
         "common/src/VmsUtils.cpp",
+        "common/src/WatchdogClient.cpp",
     ],
     shared_libs: [
         "libbase",
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 127eb98..32e5e70 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -20,9 +20,12 @@
 
 #include <iostream>
 
+#include <android/binder_process.h>
+#include <utils/Looper.h>
 #include <vhal_v2_0/EmulatedVehicleConnector.h>
 #include <vhal_v2_0/EmulatedVehicleHal.h>
 #include <vhal_v2_0/VehicleHalManager.h>
+#include <vhal_v2_0/WatchdogClient.h>
 
 using namespace android;
 using namespace android::hardware;
@@ -36,7 +39,7 @@
     auto service = std::make_unique<VehicleHalManager>(hal.get());
     connector->setValuePool(hal->getValuePool());
 
-    configureRpcThreadpool(4, true /* callerWillJoin */);
+    configureRpcThreadpool(4, false /* callerWillJoin */);
 
     ALOGI("Registering as service...");
     status_t status = service->registerAsService();
@@ -46,8 +49,22 @@
         return 1;
     }
 
+    // Setup a binder thread pool to be a car watchdog client.
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    sp<Looper> looper(Looper::prepare(0 /* opts */));
+    std::shared_ptr<WatchdogClient> watchdogClient =
+            ndk::SharedRefBase::make<WatchdogClient>(looper, service.get());
+    // The current health check is done in the main thread, so it falls short of capturing the real
+    // situation. Checking through HAL binder thread should be considered.
+    if (!watchdogClient->initialize()) {
+        ALOGE("Failed to initialize car watchdog client");
+        return 1;
+    }
     ALOGI("Ready");
-    joinRpcThreadpool();
+    while (true) {
+        looper->pollAll(-1 /* timeoutMillis */);
+    }
 
     return 1;
 }
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h
new file mode 100644
index 0000000..578606d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h
@@ -0,0 +1,74 @@
+/*
+ * 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_automotive_vehicle_V2_0_WatchdogClient_H_
+#define android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_
+
+#include "VehicleHalManager.h"
+
+#include <aidl/android/automotive/watchdog/BnCarWatchdog.h>
+#include <aidl/android/automotive/watchdog/BnCarWatchdogClient.h>
+#include <utils/Looper.h>
+#include <utils/Mutex.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+class WatchdogClient : public aidl::android::automotive::watchdog::BnCarWatchdogClient {
+  public:
+    explicit WatchdogClient(const ::android::sp<::android::Looper>& handlerLooper,
+                            VehicleHalManager* vhalManager);
+
+    ndk::ScopedAStatus checkIfAlive(
+            int32_t sessionId, aidl::android::automotive::watchdog::TimeoutLength timeout) override;
+    ndk::ScopedAStatus prepareProcessTermination() override;
+
+    bool initialize();
+
+  private:
+    class MessageHandlerImpl : public ::android::MessageHandler {
+      public:
+        explicit MessageHandlerImpl(WatchdogClient* client);
+        void handleMessage(const ::android::Message& message) override;
+
+      private:
+        WatchdogClient* mClient;
+    };
+
+  private:
+    void respondToWatchdog();
+    bool isClientHealthy() const;
+
+  private:
+    ::android::sp<::android::Looper> mHandlerLooper;
+    ::android::sp<MessageHandlerImpl> mMessageHandler;
+    std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdog> mWatchdogServer;
+    std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdogClient> mTestClient;
+    VehicleHalManager* mVhalManager;
+    ::android::Mutex mMutex;
+    int mCurrentSessionId GUARDED_BY(mMutex);
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_
diff --git a/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp b/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp
new file mode 100644
index 0000000..c067216
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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 "automotive.vehicle@2.0-watchdog"
+
+#include <common/include/vhal_v2_0/WatchdogClient.h>
+
+#include <android/binder_manager.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+using aidl::android::automotive::watchdog::ICarWatchdog;
+using aidl::android::automotive::watchdog::TimeoutLength;
+
+namespace {
+
+enum { WHAT_CHECK_ALIVE = 1 };
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+WatchdogClient::WatchdogClient(const sp<Looper>& handlerLooper, VehicleHalManager* vhalManager)
+    : mHandlerLooper(handlerLooper), mVhalManager(vhalManager), mCurrentSessionId(-1) {
+    mMessageHandler = new MessageHandlerImpl(this);
+}
+
+ndk::ScopedAStatus WatchdogClient::checkIfAlive(int32_t sessionId, TimeoutLength /*timeout*/) {
+    mHandlerLooper->removeMessages(mMessageHandler, WHAT_CHECK_ALIVE);
+    {
+        Mutex::Autolock lock(mMutex);
+        mCurrentSessionId = sessionId;
+    }
+    mHandlerLooper->sendMessage(mMessageHandler, Message(WHAT_CHECK_ALIVE));
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WatchdogClient::prepareProcessTermination() {
+    return ndk::ScopedAStatus::ok();
+}
+
+bool WatchdogClient::initialize() {
+    ndk::SpAIBinder binder(
+            AServiceManager_getService("android.automotive.watchdog.ICarWatchdog/default"));
+    if (binder.get() == nullptr) {
+        ALOGE("Failed to get carwatchdog daemon");
+        return false;
+    }
+    std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder);
+    if (server == nullptr) {
+        ALOGE("Failed to connect to carwatchdog daemon");
+        return false;
+    }
+    mWatchdogServer = server;
+
+    binder = this->asBinder();
+    if (binder.get() == nullptr) {
+        ALOGE("Failed to get car watchdog client binder object");
+        return false;
+    }
+    std::shared_ptr<ICarWatchdogClient> client = ICarWatchdogClient::fromBinder(binder);
+    if (client == nullptr) {
+        ALOGE("Failed to get ICarWatchdogClient from binder");
+        return false;
+    }
+    mTestClient = client;
+    mWatchdogServer->registerClient(client, TimeoutLength::TIMEOUT_NORMAL);
+    ALOGI("Successfully registered the client to car watchdog server");
+    return true;
+}
+
+void WatchdogClient::respondToWatchdog() {
+    if (mWatchdogServer == nullptr) {
+        ALOGW("Cannot respond to car watchdog daemon: car watchdog daemon is not connected");
+        return;
+    }
+    int sessionId;
+    {
+        Mutex::Autolock lock(mMutex);
+        sessionId = mCurrentSessionId;
+    }
+    if (isClientHealthy()) {
+        ndk::ScopedAStatus status = mWatchdogServer->tellClientAlive(mTestClient, sessionId);
+        if (!status.isOk()) {
+            ALOGE("Failed to call tellClientAlive(session id = %d): %d", sessionId,
+                  status.getStatus());
+            return;
+        }
+    }
+}
+
+bool WatchdogClient::isClientHealthy() const {
+    // We consider that default vehicle HAL is healthy if we can get PERF_VEHICLE_SPEED value.
+    StatusCode status = StatusCode::TRY_AGAIN;
+    VehiclePropValue propValue = {.prop = (int32_t)VehicleProperty::PERF_VEHICLE_SPEED};
+    while (status == StatusCode::TRY_AGAIN) {
+        mVhalManager->get(propValue,
+                          [&propValue, &status](StatusCode s, const VehiclePropValue& v) {
+                              status = s;
+                              if (s == StatusCode::OK) {
+                                  propValue = v;
+                              }
+                          });
+    }
+    return status == StatusCode::OK;
+}
+
+WatchdogClient::MessageHandlerImpl::MessageHandlerImpl(WatchdogClient* client) : mClient(client) {}
+
+void WatchdogClient::MessageHandlerImpl::handleMessage(const Message& message) {
+    switch (message.what) {
+        case WHAT_CHECK_ALIVE:
+            mClient->respondToWatchdog();
+            break;
+        default:
+            ALOGW("Unknown message: %d", message.what);
+    }
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index ee34e42..733e7dc 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2813,7 +2813,7 @@
      *
      * To query the association, the Android system gets the property, passing a VehiclePropValue
      * containing the types of associations are being queried, as defined by
-     * UserIdentificationGetRequest. The HAL must return right away, updating the VehiclePropValue
+     * UserIdentificationGetRequest. The HAL must return right away, returning a VehiclePropValue
      * with a UserIdentificationResponse. Notice that user identification should have already
      * happened while system is booting up and the VHAL implementation should only return the
      * already identified association (like the key FOB used to unlock the car), instead of starting
@@ -2828,45 +2828,50 @@
      * For example, to query if the current user (10) is associated with the FOB that unlocked the
      * car and a custom mechanism provided by the OEM, the request would be:
      *
-     * int32[0]: 10  (Android user id)
-     * int32[1]: 0   (Android user flags)
-     * int32[2]: 2   (number of types queried)
-     * int32[3]: 1   (1st type queried, UserIdentificationAssociationType::KEY_FOB)
-     * int32[4]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)
+     * int32[0]: 42  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 0   (Android user flags)
+     * int32[3]: 2   (number of types queried)
+     * int32[4]: 1   (1st type queried, UserIdentificationAssociationType::KEY_FOB)
+     * int32[5]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)
      *
      * If the user is associated with the FOB but not with the custom mechanism, the response would
      * be:
      *
-     * int32[9]: 2   (number of associations in the response)
-     * int32[1]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
-     * int32[2]: 2   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
-     * int32[3]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[4]: 4   (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)
+     * int32[0]: 42  // request id
+     * int32[1]: 2   (number of associations in the response)
+     * int32[2]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[3]: 2   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     * int32[4]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[5]: 4   (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)
      *
      * Then to associate the user with the custom mechanism, a set request would be made:
      *
-     * int32[0]: 10  (Android user id)
-     * int32[0]: 0   (Android user flags)
-     * int32[1]: 1   (number of associations being set)
-     * int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[3]: 1   (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)
+     * int32[0]: 42  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 0   (Android user flags)
+     * int32[3]: 1   (number of associations being set)
+     * int32[4]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[5]: 1   (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)
      *
      * If the request succeeded, the response would be simply:
      *
-     * int32[0]: 2   (number of associations in the response)
-     * int32[1]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[2]: 1   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     * int32[0]: 42  // request id
+     * int32[1]: 1   (number of associations in the response)
+     * int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[3]: 1   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
      *
      * Notice that the set request adds associations, but doesn't remove the existing ones. In the
      * example above, the end state would be 2 associations (FOB and CUSTOM_1). If we wanted to
      * associate the user with just CUSTOM_1 but not FOB, then the request should have been:
      *
-     * int32[0]: 10  (Android user id)
-     * int32[1]: 2   (number of types set)
-     * int32[2]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
-     * int32[3]: 2   (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER)
-     * int32[3]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[5]: 1   (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)
+     * int32[0]: 42  // request id
+     * int32[1]: 10  (Android user id)
+     * int32[2]: 2   (number of types set)
+     * int32[3]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
+     * int32[4]: 2   (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER)
+     * int32[5]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1)
+     * int32[6]: 1   (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -4639,6 +4644,11 @@
  */
 struct UserIdentificationGetRequest {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Information about the current foreground Android user.
      */
     UserInfo userInfo;
@@ -4662,6 +4672,11 @@
  */
 struct UserIdentificationSetRequest {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Information about the current foreground Android user.
      */
     UserInfo userInfo;
@@ -4674,7 +4689,7 @@
     /**
      * Associations being set.
      */
-    vec<UserIdentificationAssociationSetValue> associations;
+    vec<UserIdentificationSetAssociation> associations;
 };
 
 /**
@@ -4685,6 +4700,11 @@
  */
 struct UserIdentificationResponse {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Number of associations being returned.
      */
     int32_t numberAssociation;
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 8247ded..5ab647f 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -965,7 +965,7 @@
 
     const native_handle_t* bufferHandle = nullptr;
     bufferHandle = mGralloc->allocate(info, true, true);
-    if (bufferHandle) {
+    if (!bufferHandle) {
         GTEST_SUCCEED() << "unable to allocate protected content";
         return;
     }
@@ -1268,7 +1268,7 @@
     info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
 
     bufferHandle = mGralloc->allocate(info, true, true);
-    if (bufferHandle) {
+    if (!bufferHandle) {
         GTEST_SUCCEED() << "unable to allocate protected content";
         return;
     }
diff --git a/neuralnetworks/1.1/vts/functional/AndroidTest.xml b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..a6f812f
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?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 VtsHalNeuralnetworksV1_1TargetTest.">
+    <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="VtsHalNeuralnetworksV1_1TargetTest->/data/local/tmp/VtsHalNeuralnetworksV1_1TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <!-- b/155577050, temporarily disable the failing tests.
+             Must be deleted after corresponding driver issues are fixed.
+        -->
+        <option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalNeuralnetworksV1_1TargetTest" />
+    </test>
+</configuration>
diff --git a/neuralnetworks/1.2/vts/functional/AndroidTest.xml b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
index d9a09ab..adbdf40 100644
--- a/neuralnetworks/1.2/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
@@ -26,10 +26,10 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
-        <!-- b/155674368, b/153876253, temporarily disable the test.
+        <!-- b/155577050, b/155674368, b/153876253, temporarily disable the test.
              Must be deleted after corresponding driver issues are fixed.
         -->
-        <option name="native-test-flag" value="--gtest_filter=-*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
+        <option name="native-test-flag" value="--gtest_filter=-*Validation*:*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalNeuralnetworksV1_2TargetTest" />
     </test>
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 1db667f..2e5aca4 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -452,6 +452,10 @@
     for (const auto& s : sensors) {
         auto events = callback.getEvents(s.sensorHandle);
         auto lastEvent = events.back();
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+                     << " name=" << s.name);
 
         // Verify that only a single event has been received
         ASSERT_EQ(events.size(), 1);
@@ -578,6 +582,12 @@
 
         // Flush the sensor
         for (int32_t i = 0; i < flushCalls; i++) {
+            SCOPED_TRACE(::testing::Message()
+                         << "Flush " << i << "/" << flushCalls << ": "
+                         << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                         << sensor.sensorHandle << std::dec
+                         << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name);
+
             Result flushResult = flush(sensor.sensorHandle);
             ASSERT_EQ(flushResult, expectedResponse);
         }
@@ -595,6 +605,10 @@
 
     // Check that the correct number of flushes are present for each sensor
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
         ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount);
     }
 }
@@ -643,6 +657,11 @@
 
     activateAllSensors(false /* enable */);
     for (const SensorInfoType& sensor : getSensorsList()) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         // Call batch on inactive sensor
         // One shot sensors have minDelay set to -1 which is an invalid
         // parameter. Use 0 instead to avoid errors.
@@ -675,6 +694,11 @@
 
     // Verify that sensor events are generated when activate is called
     for (const SensorInfoType& sensor : getSensorsList()) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */);
         ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK);
 
@@ -722,6 +746,10 @@
     // Save the last received event for each sensor
     std::map<int32_t, int64_t> lastEventTimestampMap;
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
         // Some on-change sensors may not report an event without stimulus
         if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) {
             ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1);
@@ -742,6 +770,11 @@
     getEnvironment()->unregisterCallback();
 
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         // Skip sensors that did not previously report an event
         if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
             continue;
@@ -764,6 +797,12 @@
                                      RateLevel rateLevel) {
     configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel,
                        [&](Result result, int32_t reportToken) {
+                           SCOPED_TRACE(::testing::Message()
+                                        << " handle=0x" << std::hex << std::setw(8)
+                                        << std::setfill('0') << sensor.sensorHandle << std::dec
+                                        << " type=" << static_cast<int>(sensor.type)
+                                        << " name=" << sensor.name);
+
                            if (isDirectReportRateSupported(sensor, rateLevel)) {
                                ASSERT_EQ(result, Result::OK);
                                if (rateLevel != RateLevel::STOP) {
@@ -821,6 +860,11 @@
 
 void SensorsHidlTest::verifyConfigure(const SensorInfoType& sensor, SharedMemType memType,
                                       int32_t directChannelHandle, bool supportsAnyDirectChannel) {
+    SCOPED_TRACE(::testing::Message()
+                 << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                 << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                 << " name=" << sensor.name);
+
     if (isDirectChannelTypeSupported(sensor, memType)) {
         // Verify that each rate level is properly supported
         checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL);
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 7603c5b..25091a5 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
@@ -288,6 +288,49 @@
             });
     }
 }
+
+/*
+ * SetGetWapiPsk
+ */
+TEST_P(SupplicantStaNetworkHidlTest, SetGetWapiPsk) {
+    uint32_t keyMgmt = (uint32_t)ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK;
+    char kTestPskPassphrase[] = "\"123456780abcdef0123456780abcdef0deadbeef\"";
+    char kTestPskHex[] = "12345678";
+
+    if (!isWapiSupported()) {
+        GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+    }
+
+    sta_network_->setKeyMgmt_1_3(keyMgmt, [](const SupplicantStatus &status) {
+        if (SupplicantStatusCode::SUCCESS != status.code) {
+            // for unsupport case
+            EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+        }
+    });
+
+    sta_network_->setPskPassphrase(
+        kTestPskPassphrase, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getPskPassphrase(
+        [&](const SupplicantStatus &status, const hidl_string &psk) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(kTestPskPassphrase, std::string(psk.c_str()));
+        });
+
+    sta_network_->setPskPassphrase(
+        kTestPskHex, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getPskPassphrase(
+        [&](const SupplicantStatus &status, const hidl_string &psk) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(kTestPskHex, std::string(psk.c_str()));
+        });
+}
+
 /*
  * SetEapErp
  */