Merge "Specify that a read_write property can be read only in HAL" into udc-dev
diff --git a/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
index df35bae..7722ccf 100644
--- a/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
+++ b/audio/aidl/sounddose/vts/VtsHalSoundDoseFactoryTargetTest.cpp
@@ -71,6 +71,7 @@
     std::shared_ptr<ISoundDoseFactory> soundDoseFactory;
 };
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(SoundDoseFactory, GetSoundDoseForSameModule) {
     const std::string module = "primary";
 
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index e790d4f..b720305 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -3532,6 +3532,7 @@
     return ndk::ScopedAStatus::ok();
 }
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(AudioCoreSoundDose, SameInstance) {
     if (soundDose == nullptr) {
         GTEST_SKIP() << "SoundDose is not supported";
@@ -3543,6 +3544,7 @@
             << "getSoundDose must return the same interface instance across invocations";
 }
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(AudioCoreSoundDose, GetSetOutputRs2UpperBound) {
     if (soundDose == nullptr) {
         GTEST_SKIP() << "SoundDose is not supported";
@@ -3557,6 +3559,7 @@
     EXPECT_TRUE(isSupported) << "Getting/Setting RS2 upper bound must be supported";
 }
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(AudioCoreSoundDose, CheckDefaultRs2UpperBound) {
     if (soundDose == nullptr) {
         GTEST_SKIP() << "SoundDose is not supported";
@@ -3567,6 +3570,7 @@
     EXPECT_EQ(rs2Value, ISoundDose::DEFAULT_MAX_RS2);
 }
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(AudioCoreSoundDose, RegisterSoundDoseCallbackTwiceThrowsException) {
     if (soundDose == nullptr) {
         GTEST_SKIP() << "SoundDose is not supported";
@@ -3577,6 +3581,7 @@
             << "Registering sound dose callback twice should throw EX_ILLEGAL_STATE";
 }
 
+// @VsrTest = VSR-5.5-002.001
 TEST_P(AudioCoreSoundDose, RegisterSoundDoseNullCallbackThrowsException) {
     if (soundDose == nullptr) {
         GTEST_SKIP() << "SoundDose is not supported";
diff --git a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
index 5cfca61..9aabad6 100644
--- a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
+++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
@@ -97,7 +97,10 @@
     bool mTaskWaitStopped GUARDED_BY(mLock);
     // A mutex to make sure startTaskLoop does not overlap with stopTaskLoop.
     std::mutex mStartStopTaskLoopLock;
-    bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
+    bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock) = false;
+    bool mGrpcConnected GUARDED_BY(mLock) = false;
+    std::unordered_map<std::string, size_t> mClientIdToTaskCount GUARDED_BY(mLock);
+
     // Default wait time before retry connecting to remote access client is 10s.
     size_t mRetryWaitInMs = 10'000;
     std::shared_ptr<DebugRemoteTaskCallback> mDebugCallback;
@@ -110,6 +113,12 @@
 
     void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
     void dumpHelp(int fd);
+    void printCurrentStatus(int fd);
+    std::string clientIdToTaskCountToStringLocked() REQUIRES(mLock);
+    void debugInjectTask(int fd, std::string_view clientId, std::string_view taskData);
+    void updateGrpcConnected(bool connected);
+    android::base::Result<void> deliverRemoteTaskThroughCallback(const std::string& clientId,
+                                                                 std::string_view taskData);
 };
 
 }  // namespace remoteaccess
diff --git a/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc b/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc
index 6437d70..59315eb 100644
--- a/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc
+++ b/automotive/remoteaccess/hal/default/remoteaccess-tcu-test-service.rc
@@ -2,3 +2,4 @@
     class hal
     user vehicle_network
     group system inet
+    capabilities NET_RAW
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
index d944593..bbda9df 100644
--- a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -36,6 +36,8 @@
 using ::aidl::android::hardware::automotive::remoteaccess::ApState;
 using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::android::base::Error;
+using ::android::base::Result;
 using ::android::base::ScopedLockAssertion;
 using ::android::base::StringAppendF;
 using ::android::base::StringPrintf;
@@ -54,8 +56,10 @@
 constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback";
 constexpr char COMMAND_SHOW_TASK[] = "--show-task";
 constexpr char COMMAND_GET_VEHICLE_ID[] = "--get-vehicle-id";
+constexpr char COMMAND_INJECT_TASK[] = "--inject-task";
+constexpr char COMMAND_STATUS[] = "--status";
 
-std::vector<uint8_t> stringToBytes(const std::string& s) {
+std::vector<uint8_t> stringToBytes(std::string_view s) {
     const char* data = s.data();
     return std::vector<uint8_t>(data, data + s.size());
 }
@@ -81,6 +85,10 @@
     dprintf(fd, "%s, code: %d, error: %s\n", detail, status.getStatus(), status.getMessage());
 }
 
+std::string boolToString(bool x) {
+    return x ? "true" : "false";
+}
+
 }  // namespace
 
 RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
@@ -126,6 +134,33 @@
     mTaskLoopRunning = false;
 }
 
+void RemoteAccessService::updateGrpcConnected(bool connected) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+    mGrpcConnected = connected;
+}
+
+Result<void> RemoteAccessService::deliverRemoteTaskThroughCallback(const std::string& clientId,
+                                                                   std::string_view taskData) {
+    std::shared_ptr<IRemoteTaskCallback> callback;
+    {
+        std::lock_guard<std::mutex> lockGuard(mLock);
+        callback = mRemoteTaskCallback;
+        mClientIdToTaskCount[clientId] += 1;
+    }
+    if (callback == nullptr) {
+        return Error() << "No callback registered, task ignored";
+    }
+    ALOGD("Calling onRemoteTaskRequested callback for client ID: %s", clientId.c_str());
+    ScopedAStatus callbackStatus =
+            callback->onRemoteTaskRequested(clientId, stringToBytes(taskData));
+    if (!callbackStatus.isOk()) {
+        return Error() << "Failed to call onRemoteTaskRequested callback, status: "
+                       << callbackStatus.getStatus()
+                       << ", message: " << callbackStatus.getMessage();
+    }
+    return {};
+}
+
 void RemoteAccessService::runTaskLoop() {
     GetRemoteTasksRequest request = {};
     std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
@@ -135,28 +170,19 @@
             mGetRemoteTasksContext.reset(new ClientContext());
             reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
         }
+        updateGrpcConnected(true);
         GetRemoteTasksResponse response;
         while (reader->Read(&response)) {
             ALOGI("Receiving one task from remote task client");
 
-            std::shared_ptr<IRemoteTaskCallback> callback;
-            {
-                std::lock_guard<std::mutex> lockGuard(mLock);
-                callback = mRemoteTaskCallback;
-            }
-            if (callback == nullptr) {
-                ALOGD("No callback registered, task ignored");
+            if (auto result =
+                        deliverRemoteTaskThroughCallback(response.clientid(), response.data());
+                !result.ok()) {
+                ALOGE("%s", result.error().message().c_str());
                 continue;
             }
-            ALOGD("Calling onRemoteTaskRequested callback for client ID: %s",
-                  response.clientid().c_str());
-            ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
-                    response.clientid(), stringToBytes(response.data()));
-            if (!callbackStatus.isOk()) {
-                ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
-                      callbackStatus.getStatus(), callbackStatus.getMessage());
-            }
         }
+        updateGrpcConnected(false);
         Status status = reader->Finish();
         mGetRemoteTasksContext.reset();
 
@@ -252,15 +278,17 @@
 }
 
 void RemoteAccessService::dumpHelp(int fd) {
-    dprintf(fd, "%s",
-            (std::string("RemoteAccess HAL debug interface, Usage: \n") + COMMAND_SET_AP_STATE +
-             " [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired)  Set the new AP state\n" +
-             COMMAND_START_DEBUG_CALLBACK +
-             " Start a debug callback that will record the received tasks\n" +
-             COMMAND_STOP_DEBUG_CALLBACK + " Stop the debug callback\n" + COMMAND_SHOW_TASK +
-             " Show tasks received by debug callback\n" + COMMAND_GET_VEHICLE_ID +
-             " Get vehicle id\n")
-                    .c_str());
+    dprintf(fd,
+            "RemoteAccess HAL debug interface, Usage: \n"
+            "%s [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired): Set the new AP state\n"
+            "%s: Start a debug callback that will record the received tasks\n"
+            "%s: Stop the debug callback\n"
+            "%s: Show tasks received by debug callback\n"
+            "%s: Get vehicle id\n"
+            "%s [client_id] [task_data]: Inject a task\n"
+            "%s: Show status\n",
+            COMMAND_SET_AP_STATE, COMMAND_START_DEBUG_CALLBACK, COMMAND_STOP_DEBUG_CALLBACK,
+            COMMAND_SHOW_TASK, COMMAND_GET_VEHICLE_ID, COMMAND_INJECT_TASK, COMMAND_STATUS);
 }
 
 binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) {
@@ -271,6 +299,7 @@
 
     if (numArgs == 0) {
         dumpHelp(fd);
+        printCurrentStatus(fd);
         return STATUS_OK;
     }
 
@@ -330,6 +359,14 @@
         } else {
             dprintf(fd, "Vehicle Id: %s\n", vehicleId.c_str());
         }
+    } else if (!strcmp(args[0], COMMAND_INJECT_TASK)) {
+        if (numArgs < 3) {
+            dumpHelp(fd);
+            return STATUS_OK;
+        }
+        debugInjectTask(fd, args[1], args[2]);
+    } else if (!strcmp(args[0], COMMAND_STATUS)) {
+        printCurrentStatus(fd);
     } else {
         dumpHelp(fd);
     }
@@ -337,6 +374,37 @@
     return STATUS_OK;
 }
 
+void RemoteAccessService::printCurrentStatus(int fd) {
+    std::lock_guard<std::mutex> lockGuard(mLock);
+    dprintf(fd,
+            "\nRemoteAccess HAL status \n"
+            "Remote task callback registered: %s\n"
+            "Task receiving GRPC connection established: %s\n"
+            "Received task count by clientId: \n%s\n",
+            boolToString(mRemoteTaskCallback.get()).c_str(), boolToString(mGrpcConnected).c_str(),
+            clientIdToTaskCountToStringLocked().c_str());
+}
+
+void RemoteAccessService::debugInjectTask(int fd, std::string_view clientId,
+                                          std::string_view taskData) {
+    std::string clientIdCopy = std::string(clientId);
+    if (auto result = deliverRemoteTaskThroughCallback(clientIdCopy, taskData); !result.ok()) {
+        dprintf(fd, "Failed to inject task: %s", result.error().message().c_str());
+        return;
+    }
+    dprintf(fd, "Task for client: %s, data: [%s] successfully injected\n", clientId.data(),
+            taskData.data());
+}
+
+std::string RemoteAccessService::clientIdToTaskCountToStringLocked() {
+    // Print the table header
+    std::string output = "| ClientId | Count |\n";
+    for (const auto& [clientId, taskCount] : mClientIdToTaskCount) {
+        output += StringPrintf("  %-9s  %-6zu\n", clientId.c_str(), taskCount);
+    }
+    return output;
+}
+
 ScopedAStatus DebugRemoteTaskCallback::onRemoteTaskRequested(const std::string& clientId,
                                                              const std::vector<uint8_t>& data) {
     std::lock_guard<std::mutex> lockGuard(mLock);
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index 28790e2..ae36290 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -2371,7 +2371,7 @@
                     66.19999694824219,
                     "VehicleUnit::FAHRENHEIT",
                     19.0,
-                    66.5
+                    66.0
                 ]
             }
         },
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
index 6fd2367..7b74092 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/include/FakeVehicleHardware.h
@@ -178,6 +178,13 @@
     void eventFromVehicleBus(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value);
 
+    int getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp, int increment);
+    void updateHvacTemperatureValueSuggestionInput(
+            const std::vector<int>& hvacTemperatureSetConfigArray,
+            std::vector<float>* hvacTemperatureValueSuggestionInput);
+    VhalResult<void> setHvacTemperatureValueSuggestion(
+            const aidl::android::hardware::automotive::vehicle::VehiclePropValue&
+                    hvacTemperatureValueSuggestion);
     VhalResult<void> maybeSetSpecialValue(
             const aidl::android::hardware::automotive::vehicle::VehiclePropValue& value,
             bool* isSpecialValue);
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
index 78c21e9..4544389 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/src/FakeVehicleHardware.cpp
@@ -67,6 +67,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
 
 using ::android::base::EqualsIgnoreCase;
 using ::android::base::Error;
@@ -298,6 +299,94 @@
     return {};
 }
 
+int FakeVehicleHardware::getHvacTempNumIncrements(int requestedTemp, int minTemp, int maxTemp,
+                                                  int increment) {
+    requestedTemp = std::max(requestedTemp, minTemp);
+    requestedTemp = std::min(requestedTemp, maxTemp);
+    int numIncrements = (requestedTemp - minTemp) / increment;
+    return numIncrements;
+}
+
+void FakeVehicleHardware::updateHvacTemperatureValueSuggestionInput(
+        const std::vector<int>& hvacTemperatureSetConfigArray,
+        std::vector<float>* hvacTemperatureValueSuggestionInput) {
+    int minTempInCelsius = hvacTemperatureSetConfigArray[0];
+    int maxTempInCelsius = hvacTemperatureSetConfigArray[1];
+    int incrementInCelsius = hvacTemperatureSetConfigArray[2];
+
+    int minTempInFahrenheit = hvacTemperatureSetConfigArray[3];
+    int maxTempInFahrenheit = hvacTemperatureSetConfigArray[4];
+    int incrementInFahrenheit = hvacTemperatureSetConfigArray[5];
+
+    // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
+    // by 10 and converted to integers. Therefore, requestedTemp must also be multiplied by 10 and
+    // converted to an integer in order for them to be the same units.
+    int requestedTemp = static_cast<int>((*hvacTemperatureValueSuggestionInput)[0] * 10.0f);
+    int numIncrements =
+            (*hvacTemperatureValueSuggestionInput)[1] == toInt(VehicleUnit::CELSIUS)
+                    ? getHvacTempNumIncrements(requestedTemp, minTempInCelsius, maxTempInCelsius,
+                                               incrementInCelsius)
+                    : getHvacTempNumIncrements(requestedTemp, minTempInFahrenheit,
+                                               maxTempInFahrenheit, incrementInFahrenheit);
+
+    int suggestedTempInCelsius = minTempInCelsius + incrementInCelsius * numIncrements;
+    int suggestedTempInFahrenheit = minTempInFahrenheit + incrementInFahrenheit * numIncrements;
+    // HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature values to be in the original
+    // floating point form so we divide by 10 and convert to float.
+    (*hvacTemperatureValueSuggestionInput)[2] = static_cast<float>(suggestedTempInCelsius) / 10.0f;
+    (*hvacTemperatureValueSuggestionInput)[3] =
+            static_cast<float>(suggestedTempInFahrenheit) / 10.0f;
+}
+
+VhalResult<void> FakeVehicleHardware::setHvacTemperatureValueSuggestion(
+        const VehiclePropValue& hvacTemperatureValueSuggestion) {
+    auto hvacTemperatureSetConfigResult =
+            mServerSidePropStore->getConfig(toInt(VehicleProperty::HVAC_TEMPERATURE_SET));
+
+    if (!hvacTemperatureSetConfigResult.ok()) {
+        return StatusError(getErrorCode(hvacTemperatureSetConfigResult)) << StringPrintf(
+                       "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because"
+                       " HVAC_TEMPERATURE_SET could not be retrieved. Error: %s",
+                       getErrorMsg(hvacTemperatureSetConfigResult).c_str());
+    }
+
+    const auto& originalInput = hvacTemperatureValueSuggestion.value.floatValues;
+    if (originalInput.size() != 4) {
+        return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
+                       "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
+                       " array value is not size 4.");
+    }
+
+    bool isTemperatureUnitSpecified = originalInput[1] == toInt(VehicleUnit::CELSIUS) ||
+                                      originalInput[1] == toInt(VehicleUnit::FAHRENHEIT);
+    if (!isTemperatureUnitSpecified) {
+        return StatusError(StatusCode::INVALID_ARG) << StringPrintf(
+                       "Failed to set HVAC_TEMPERATURE_VALUE_SUGGESTION because float"
+                       " value at index 1 is not any of %d or %d, which corresponds to"
+                       " VehicleUnit#CELSIUS and VehicleUnit#FAHRENHEIT respectively.",
+                       toInt(VehicleUnit::CELSIUS), toInt(VehicleUnit::FAHRENHEIT));
+    }
+
+    auto updatedValue = mValuePool->obtain(hvacTemperatureValueSuggestion);
+    const auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfigResult.value()->configArray;
+    auto& hvacTemperatureValueSuggestionInput = updatedValue->value.floatValues;
+
+    updateHvacTemperatureValueSuggestionInput(hvacTemperatureSetConfigArray,
+                                              &hvacTemperatureValueSuggestionInput);
+
+    updatedValue->timestamp = elapsedRealtimeNano();
+    auto writeResult = mServerSidePropStore->writeValue(std::move(updatedValue),
+                                                        /* updateStatus = */ true,
+                                                        VehiclePropertyStore::EventMode::ALWAYS);
+    if (!writeResult.ok()) {
+        return StatusError(getErrorCode(writeResult))
+               << StringPrintf("failed to write value into property store, error: %s",
+                               getErrorMsg(writeResult).c_str());
+    }
+
+    return {};
+}
+
 bool FakeVehicleHardware::isHvacPropAndHvacNotAvailable(int32_t propId, int32_t areaId) const {
     std::unordered_set<int32_t> powerProps(std::begin(HVAC_POWER_PROPERTIES),
                                            std::end(HVAC_POWER_PROPERTIES));
@@ -491,6 +580,9 @@
         case VENDOR_PROPERTY_ID:
             *isSpecialValue = true;
             return StatusError((StatusCode)VENDOR_ERROR_CODE);
+        case toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION):
+            *isSpecialValue = true;
+            return setHvacTemperatureValueSuggestion(value);
 
 #ifdef ENABLE_VEHICLE_HAL_TEST_PROPERTIES
         case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
diff --git a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
index 93a63ad..a50b4ad 100644
--- a/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
+++ b/automotive/vehicle/aidl/impl/fake_impl/hardware/test/FakeVehicleHardwareTest.cpp
@@ -57,6 +57,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VehicleUnit;
 using ::android::base::expected;
 using ::android::base::ScopedLockAssertion;
 using ::android::base::StringPrintf;
@@ -2242,6 +2243,359 @@
     }
 }
 
+TEST_F(FakeVehicleHardwareTest, testSetHvacTemperatureValueSuggestion) {
+    float CELSIUS = static_cast<float>(toInt(VehicleUnit::CELSIUS));
+    float FAHRENHEIT = static_cast<float>(toInt(VehicleUnit::FAHRENHEIT));
+
+    VehiclePropValue floatArraySizeFour = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = HVAC_ALL,
+            .value.floatValues = {0, CELSIUS, 0, 0},
+    };
+    StatusCode status = setValue(floatArraySizeFour);
+    EXPECT_EQ(status, StatusCode::OK);
+
+    VehiclePropValue floatArraySizeZero = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = HVAC_ALL,
+    };
+    status = setValue(floatArraySizeZero);
+    EXPECT_EQ(status, StatusCode::INVALID_ARG);
+
+    VehiclePropValue floatArraySizeFive = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = HVAC_ALL,
+            .value.floatValues = {0, CELSIUS, 0, 0, 0},
+    };
+    status = setValue(floatArraySizeFive);
+    EXPECT_EQ(status, StatusCode::INVALID_ARG);
+
+    VehiclePropValue invalidUnit = {
+            .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+            .areaId = HVAC_ALL,
+            .value.floatValues = {0, 0, 0, 0},
+    };
+    status = setValue(floatArraySizeFive);
+    EXPECT_EQ(status, StatusCode::INVALID_ARG);
+    clearChangedProperties();
+
+    // Config array values from HVAC_TEMPERATURE_SET in DefaultProperties.json
+    auto configs = getHardware()->getAllPropertyConfigs();
+    VehiclePropConfig* hvacTemperatureSetConfig = nullptr;
+    for (auto& config : configs) {
+        if (config.prop == toInt(VehicleProperty::HVAC_TEMPERATURE_SET)) {
+            hvacTemperatureSetConfig = &config;
+            break;
+        }
+    }
+    EXPECT_NE(hvacTemperatureSetConfig, nullptr);
+
+    auto& hvacTemperatureSetConfigArray = hvacTemperatureSetConfig->configArray;
+    // The HVAC_TEMPERATURE_SET config array values are temperature values that have been multiplied
+    // by 10 and converted to integers. HVAC_TEMPERATURE_VALUE_SUGGESTION specifies the temperature
+    // values to be in the original floating point form so we divide by 10 and convert to float.
+    float minTempInCelsius = hvacTemperatureSetConfigArray[0] / 10.0f;
+    float maxTempInCelsius = hvacTemperatureSetConfigArray[1] / 10.0f;
+    float incrementInCelsius = hvacTemperatureSetConfigArray[2] / 10.0f;
+    float minTempInFahrenheit = hvacTemperatureSetConfigArray[3] / 10.0f;
+    float maxTempInFahrenheit = hvacTemperatureSetConfigArray[4] / 10.0f;
+    float incrementInFahrenheit = hvacTemperatureSetConfigArray[5] / 10.0f;
+
+    auto testCases = {
+            SetSpecialValueTestCase{
+                    .name = "min_celsius_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInCelsius, CELSIUS, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInCelsius, CELSIUS,
+                                                                  minTempInCelsius,
+                                                                  minTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "min_fahrenheit_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
+                                                                  0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInFahrenheit, FAHRENHEIT,
+                                                                  minTempInCelsius,
+                                                                  minTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "max_celsius_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInCelsius, CELSIUS, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInCelsius, CELSIUS,
+                                                                  maxTempInCelsius,
+                                                                  maxTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "max_fahrenheit_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
+                                                                  0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInFahrenheit, FAHRENHEIT,
+                                                                  maxTempInCelsius,
+                                                                  maxTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "below_min_celsius_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInCelsius - 1, CELSIUS, 0,
+                                                                  0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInCelsius - 1, CELSIUS,
+                                                                  minTempInCelsius,
+                                                                  minTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "below_min_fahrenheit_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInFahrenheit - 1,
+                                                                  FAHRENHEIT, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInFahrenheit - 1,
+                                                                  FAHRENHEIT, minTempInCelsius,
+                                                                  minTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "above_max_celsius_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInCelsius + 1, CELSIUS, 0,
+                                                                  0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInCelsius + 1, CELSIUS,
+                                                                  maxTempInCelsius,
+                                                                  maxTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "above_max_fahrenheit_temperature",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInFahrenheit + 1,
+                                                                  FAHRENHEIT, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {maxTempInFahrenheit + 1,
+                                                                  FAHRENHEIT, maxTempInCelsius,
+                                                                  maxTempInFahrenheit},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "inbetween_value_celsius",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInCelsius +
+                                                                          incrementInCelsius * 2.5f,
+                                                                  CELSIUS, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues =
+                                                    {minTempInCelsius + incrementInCelsius * 2.5f,
+                                                     CELSIUS,
+                                                     minTempInCelsius + incrementInCelsius * 2,
+                                                     minTempInFahrenheit +
+                                                             incrementInFahrenheit * 2},
+                                    },
+                            },
+            },
+            SetSpecialValueTestCase{
+                    .name = "inbetween_value_fahrenheit",
+                    .valuesToSet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues = {minTempInFahrenheit +
+                                                                          incrementInFahrenheit *
+                                                                                  2.5f,
+                                                                  FAHRENHEIT, 0, 0},
+                                    },
+                            },
+                    .expectedValuesToGet =
+                            {
+                                    VehiclePropValue{
+                                            .prop = toInt(
+                                                    VehicleProperty::
+                                                            HVAC_TEMPERATURE_VALUE_SUGGESTION),
+                                            .areaId = HVAC_ALL,
+                                            .value.floatValues =
+                                                    {minTempInFahrenheit +
+                                                             incrementInFahrenheit * 2.5f,
+                                                     FAHRENHEIT,
+                                                     minTempInCelsius + incrementInCelsius * 2,
+                                                     minTempInFahrenheit +
+                                                             incrementInFahrenheit * 2},
+                                    },
+                            },
+            },
+    };
+
+    for (auto& tc : testCases) {
+        StatusCode status = setValue(tc.valuesToSet[0]);
+        EXPECT_EQ(status, StatusCode::OK);
+
+        auto events = getChangedProperties();
+        EXPECT_EQ(events.size(), static_cast<size_t>(1));
+        events[0].timestamp = 0;
+
+        EXPECT_EQ(events[0], (tc.expectedValuesToGet[0]))
+                << "Failed Test: " << tc.name << "\n"
+                << "Received - prop: " << events[0].prop << ", areaId: " << events[0].areaId
+                << ", floatValues: {" << events[0].value.floatValues[0] << ", "
+                << events[0].value.floatValues[1] << ", " << events[0].value.floatValues[2] << ", "
+                << events[0].value.floatValues[3] << "}\n"
+                << "Expected - prop: " << tc.expectedValuesToGet[0].prop
+                << ", areaId: " << tc.expectedValuesToGet[0].areaId << ", floatValues: {"
+                << tc.expectedValuesToGet[0].value.floatValues[0] << ", "
+                << tc.expectedValuesToGet[0].value.floatValues[1] << ", "
+                << tc.expectedValuesToGet[0].value.floatValues[2] << ", "
+                << tc.expectedValuesToGet[0].value.floatValues[3] << "}\n";
+        clearChangedProperties();
+    }
+}
+
 }  // namespace fake
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 2dc453c..8a3ab90 100644
--- a/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl_property/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -2668,7 +2668,12 @@
      * when computing the vehicle's location that is shared with Android through the GNSS HAL.
      *
      * The value must return a collection of bit flags. The bit flags are defined in
-     * LocationCharacterization.
+     * LocationCharacterization. The value must also include exactly one of DEAD_RECKONED or
+     * RAW_GNSS_ONLY among its collection of bit flags.
+     *
+     * When this property is not supported, it is assumed that no additional sensor inputs are fused
+     * into the GNSS updates provided through the GNSS HAL. That is unless otherwise specified
+     * through the GNSS HAL interfaces.
      *
      * @change_mode VehiclePropertyChangeMode.STATIC
      * @access VehiclePropertyAccess.READ
diff --git a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
index 69d4789..783ce11 100644
--- a/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
+++ b/health/aidl/vts/functional/VtsHalHealthTargetTest.cpp
@@ -257,7 +257,7 @@
     BatteryChargingPolicy value;
 
     /* set ChargingPolicy*/
-    status = health->setChargingPolicy(static_cast<BatteryChargingPolicy>(2));  // LONG_LIFE
+    status = health->setChargingPolicy(BatteryChargingPolicy::LONG_LIFE);
     ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
     if (!status.isOk()) return;
 
@@ -265,7 +265,9 @@
     status = health->getChargingPolicy(&value);
     ASSERT_THAT(status, AnyOf(IsOk(), ExceptionIs(EX_UNSUPPORTED_OPERATION)));
     if (!status.isOk()) return;
-    ASSERT_THAT(static_cast<int>(value), Eq(2));
+    // the result of getChargingPolicy will be one of default(1), ADAPTIVE_AON(2)
+    // ADAPTIVE_AC(3) or LONG_LIFE(4). default(1) means NOT_SUPPORT
+    ASSERT_THAT(static_cast<int>(value), AnyOf(Eq(1), Eq(4)));
 }
 
 MATCHER(IsValidHealthData, "") {
diff --git a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
index dcf8451..e344458 100644
--- a/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/aidl/vts/functional/GeneratedTestHarness.cpp
@@ -736,8 +736,8 @@
                     // If a sync fence is returned, try start another run waiting for the sync
                     // fence.
                     if (testConfig.reusable) {
-                        ret = execution->executeFenced(waitFor, kNoDeadline, kNoDuration,
-                                                       &executionResult);
+                        // Nothing to do because at most one execution may occur on a reusable
+                        // execution object at any given time.
                     } else if (testConfig.useConfig) {
                         ret = preparedModel->executeFencedWithConfig(
                                 request, waitFor,
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 5539b9c..316c308 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -565,9 +565,9 @@
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band17;
-    band17.eutranBands() = {::android::hardware::radio::V1_5::EutranBands::BAND_17};
+    band17.eutranBands({::android::hardware::radio::V1_5::EutranBands::BAND_17});
     ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band20;
-    band20.eutranBands() = {::android::hardware::radio::V1_5::EutranBands::BAND_20};
+    band20.eutranBands({::android::hardware::radio::V1_5::EutranBands::BAND_20});
     ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier17 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::EUTRAN,
             .bands = band17,
diff --git a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
index 0925a21..839a4ff 100644
--- a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
+++ b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
@@ -284,14 +284,21 @@
 
 TEST_P(SecureElementAidl, transmit) {
     std::vector<uint8_t> response;
+    LogicalChannelResponse logical_channel_response;
 
-    // transmit called after init shall succeed.
-    // Note: no channel is opened for this test and the transmit
-    // response will have the status SW_LOGICAL_CHANNEL_NOT_SUPPORTED.
-    // The transmit response shall be larger than 2 bytes as it includes the
-    // status code.
-    EXPECT_OK(secure_element_->transmit(kDataApdu, &response));
-    EXPECT_GE(response.size(), 2u);
+    // Note: no channel is opened for this test
+    // transmit() will return an empty response with the error
+    // code CHANNEL_NOT_AVAILABLE when the SE cannot be
+    // communicated with.
+    EXPECT_ERR(secure_element_->transmit(kDataApdu, &response));
+
+    EXPECT_OK(secure_element_->openLogicalChannel(kSelectableAid, 0x00, &logical_channel_response));
+    EXPECT_GE(logical_channel_response.selectResponse.size(), 2u);
+    EXPECT_GE(logical_channel_response.channelNumber, 1u);
+    EXPECT_LE(logical_channel_response.channelNumber, 19u);
+
+    // transmit called on the logical channel should succeed.
+    EXPECT_EQ(transmit(logical_channel_response.channelNumber), 0x9000);
 }
 
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementAidl);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index c6b8906..c45dd3f 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -590,8 +590,7 @@
     return name.substr(pos + 1);
 }
 
-bool matching_rp_instance(const string& km_name,
-                          std::shared_ptr<IRemotelyProvisionedComponent>* rp) {
+std::shared_ptr<IRemotelyProvisionedComponent> matching_rp_instance(const std::string& km_name) {
     string km_suffix = device_suffix(km_name);
 
     vector<string> rp_names =
@@ -601,11 +600,10 @@
         // KeyMint instance, assume they match.
         if (device_suffix(rp_name) == km_suffix && AServiceManager_isDeclared(rp_name.c_str())) {
             ::ndk::SpAIBinder binder(AServiceManager_waitForService(rp_name.c_str()));
-            *rp = IRemotelyProvisionedComponent::fromBinder(binder);
-            return true;
+            return IRemotelyProvisionedComponent::fromBinder(binder);
         }
     }
-    return false;
+    return nullptr;
 }
 
 }  // namespace
@@ -1140,11 +1138,14 @@
         GTEST_SKIP() << "RKP support is not required on this platform";
     }
 
-    // There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
-    // instance.
-    std::shared_ptr<IRemotelyProvisionedComponent> rp;
-    ASSERT_TRUE(matching_rp_instance(GetParam(), &rp))
-            << "No IRemotelyProvisionedComponent found that matches KeyMint device " << GetParam();
+    // Check for an IRemotelyProvisionedComponent instance associated with the
+    // KeyMint instance.
+    std::shared_ptr<IRemotelyProvisionedComponent> rp = matching_rp_instance(GetParam());
+    if (rp == nullptr && SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Encountered StrongBox implementation that does not support RKP";
+    }
+    ASSERT_NE(rp, nullptr) << "No IRemotelyProvisionedComponent found that matches KeyMint device "
+                           << GetParam();
 
     // Generate a P-256 keypair to use as an attestation key.
     MacedPublicKey macedPubKey;
@@ -1218,11 +1219,14 @@
         GTEST_SKIP() << "RKP support is not required on this platform";
     }
 
-    // There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
-    // instance.
-    std::shared_ptr<IRemotelyProvisionedComponent> rp;
-    ASSERT_TRUE(matching_rp_instance(GetParam(), &rp))
-            << "No IRemotelyProvisionedComponent found that matches KeyMint device " << GetParam();
+    // Check for an IRemotelyProvisionedComponent instance associated with the
+    // KeyMint instance.
+    std::shared_ptr<IRemotelyProvisionedComponent> rp = matching_rp_instance(GetParam());
+    if (rp == nullptr && SecLevel() == SecurityLevel::STRONGBOX) {
+        GTEST_SKIP() << "Encountered StrongBox implementation that does not support RKP";
+    }
+    ASSERT_NE(rp, nullptr) << "No IRemotelyProvisionedComponent found that matches KeyMint device "
+                           << GetParam();
 
     // Generate a P-256 keypair to use as an attestation key.
     MacedPublicKey macedPubKey;
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 086ee79..7214234 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -22,6 +22,7 @@
 #include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
 
 #include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
+#include <android-base/macros.h>
 #include <android-base/properties.h>
 #include <cppbor.h>
 #include <hwtrust/hwtrust.h>
@@ -43,6 +44,7 @@
 constexpr int32_t kBccPayloadSubjPubKey = -4670552;
 constexpr int32_t kBccPayloadKeyUsage = -4670553;
 constexpr int kP256AffinePointSize = 32;
+constexpr uint32_t kNumTeeDeviceInfoEntries = 14;
 
 using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
 using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
@@ -388,6 +390,11 @@
     return entryName + " has an invalid value.\n";
 }
 
+bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
+    return devInfo.get("security_level") && devInfo.get("security_level")->asTstr() &&
+           devInfo.get("security_level")->asTstr()->value() == "tee";
+}
+
 ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
         const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
         bool isFactory) {
@@ -396,6 +403,21 @@
     const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
     const cppbor::Array kValidAttIdStates = {"locked", "open"};
     const cppbor::Array kValidFused = {0, 1};
+    constexpr std::array<std::string_view, kNumTeeDeviceInfoEntries> kDeviceInfoKeys = {
+            "brand",
+            "manufacturer",
+            "product",
+            "model",
+            "device",
+            "vb_state",
+            "bootloader_state",
+            "vbmeta_digest",
+            "os_version",
+            "system_patch_level",
+            "boot_patch_level",
+            "vendor_patch_level",
+            "security_level",
+            "fused"};
 
     struct AttestationIdEntry {
         const char* id;
@@ -439,20 +461,48 @@
     }
 
     std::string error;
+    std::string tmp;
+    std::set<std::string_view> previousKeys;
     switch (info.versionNumber) {
         case 3:
+            if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
+                error += fmt::format(
+                        "Err: Incorrect number of device info entries. Expected {} but got"
+                        "{}\n",
+                        kNumTeeDeviceInfoEntries, parsed->size());
+            }
+            // TEE IRPC instances require all entries to be present in DeviceInfo. Non-TEE instances
+            // may omit `os_version`
+            if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries ||
+                                              parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
+                error += fmt::format(
+                        "Err: Incorrect number of device info entries. Expected {} or {} but got"
+                        "{}\n",
+                        kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
+            }
+            for (auto& [key, _] : *parsed) {
+                const std::string& keyValue = key->asTstr()->value();
+                if (!previousKeys.insert(keyValue).second) {
+                    error += "Err: Duplicate device info entry: <" + keyValue + ">,\n";
+                }
+                if (std::find(kDeviceInfoKeys.begin(), kDeviceInfoKeys.end(), keyValue) ==
+                    kDeviceInfoKeys.end()) {
+                    error += "Err: Unrecognized key entry: <" + key->asTstr()->value() + ">,\n";
+                }
+            }
+            FALLTHROUGH_INTENDED;
         case 2:
             for (const auto& entry : kAttestationIdEntrySet) {
-                error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
-                                       entry.id);
+                tmp = checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
+                                    entry.id);
             }
-            if (!error.empty()) {
-                return error +
-                       "Attestation IDs are missing or malprovisioned. If this test is being\n"
-                       "run against an early proto or EVT build, this error is probably WAI\n"
-                       "and indicates that Device IDs were not provisioned in the factory. If\n"
-                       "this error is returned on a DVT or later build revision, then\n"
-                       "something is likely wrong with the factory provisioning process.";
+            if (!tmp.empty()) {
+                error += tmp +
+                         "Attestation IDs are missing or malprovisioned. If this test is being\n"
+                         "run against an early proto or EVT build, this error is probably WAI\n"
+                         "and indicates that Device IDs were not provisioned in the factory. If\n"
+                         "this error is returned on a DVT or later build revision, then\n"
+                         "something is likely wrong with the factory provisioning process.";
             }
             // TODO: Refactor the KeyMint code that validates these fields and include it here.
             error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
@@ -465,8 +515,7 @@
             error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
             error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
                                    kValidSecurityLevels);
-            if (parsed->get("security_level") && parsed->get("security_level")->asTstr() &&
-                parsed->get("security_level")->asTstr()->value() == "tee") {
+            if (isTeeDeviceInfo(*parsed)) {
                 error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
             }
             break;
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/INonStandardCertCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/INonStandardCertCallback.aidl
index 2f9e528..2e11c76 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/INonStandardCertCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/INonStandardCertCallback.aidl
@@ -18,7 +18,8 @@
 
 /**
  * Callback to allow supplicant to retrieve non-standard certificate types
- * from the client.
+ * from the framework. Certificates can be stored in the framework using
+ * the WifiKeystore#put system API.
  *
  * Must be registered by the client at initialization, so that
  * supplicant can call into the client to retrieve any values.