Merge "Filter unsupported propIds for current version." into main
diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp
index c29345f..20bba7f 100644
--- a/automotive/vehicle/aidl/impl/vhal/Android.bp
+++ b/automotive/vehicle/aidl/impl/vhal/Android.bp
@@ -61,6 +61,7 @@
     ],
     header_libs: [
         "IVehicleHardware",
+        "IVehicleGeneratedHeaders",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
index f7a71b4..250b30c 100644
--- a/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
+++ b/automotive/vehicle/aidl/impl/vhal/include/DefaultVehicleHal.h
@@ -49,6 +49,9 @@
 
     explicit DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware);
 
+    // Test-only
+    DefaultVehicleHal(std::unique_ptr<IVehicleHardware> hardware, int32_t testInterfaceVersion);
+
     ~DefaultVehicleHal();
 
     ndk::ScopedAStatus getAllPropConfigs(
@@ -153,6 +156,8 @@
             mPropertyChangeEventsBatchingConsumer;
     // Only set once during initialization.
     std::chrono::nanoseconds mEventBatchingWindow;
+    // Only used for testing.
+    int32_t mTestInterfaceVersion = 0;
 
     std::mutex mLock;
     std::unordered_map<const AIBinder*, std::unique_ptr<OnBinderDiedContext>> mOnBinderDiedContexts
@@ -227,6 +232,8 @@
             std::vector<aidl::android::hardware::automotive::vehicle::VehiclePropValue>&&
                     batchedEvents);
 
+    int32_t getVhalInterfaceVersion();
+
     // Puts the property change events into a queue so that they can handled in batch.
     static void batchPropertyChangeEvent(
             const std::weak_ptr<ConcurrentQueue<
diff --git a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
index 76d2f31..cc5edcc 100644
--- a/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/src/DefaultVehicleHal.cpp
@@ -22,6 +22,7 @@
 #include <LargeParcelableBase.h>
 #include <VehicleHalTypes.h>
 #include <VehicleUtils.h>
+#include <VersionForVehicleProperty.h>
 
 #include <android-base/result.h>
 #include <android-base/stringprintf.h>
@@ -61,6 +62,7 @@
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
 using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+using ::aidl::android::hardware::automotive::vehicle::VersionForVehicleProperty;
 using ::android::automotive::car_binder_lib::LargeParcelableBase;
 using ::android::base::Error;
 using ::android::base::expected;
@@ -94,8 +96,13 @@
 }  // namespace
 
 DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware)
+    : DefaultVehicleHal(std::move(vehicleHardware), /* testInterfaceVersion= */ 0){};
+
+DefaultVehicleHal::DefaultVehicleHal(std::unique_ptr<IVehicleHardware> vehicleHardware,
+                                     int32_t testInterfaceVersion)
     : mVehicleHardware(std::move(vehicleHardware)),
-      mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)) {
+      mPendingRequestPool(std::make_shared<PendingRequestPool>(TIMEOUT_IN_NANO)),
+      mTestInterfaceVersion(testInterfaceVersion) {
     if (!getAllPropConfigsFromHardware()) {
         return;
     }
@@ -312,13 +319,46 @@
     mPendingRequestPool = std::make_unique<PendingRequestPool>(timeoutInNano);
 }
 
+int32_t DefaultVehicleHal::getVhalInterfaceVersion() {
+    if (mTestInterfaceVersion != 0) {
+        return mTestInterfaceVersion;
+    }
+    int32_t myVersion = 0;
+    getInterfaceVersion(&myVersion);
+    return myVersion;
+}
+
 bool DefaultVehicleHal::getAllPropConfigsFromHardware() {
     auto configs = mVehicleHardware->getAllPropertyConfigs();
+    std::vector<VehiclePropConfig> filteredConfigs;
+    int32_t myVersion = getVhalInterfaceVersion();
     for (auto& config : configs) {
+        if (!isSystemProp(config.prop)) {
+            filteredConfigs.push_back(std::move(config));
+            continue;
+        }
+        VehicleProperty property = static_cast<VehicleProperty>(config.prop);
+        std::string propertyName = aidl::android::hardware::automotive::vehicle::toString(property);
+        auto it = VersionForVehicleProperty.find(property);
+        if (it == VersionForVehicleProperty.end()) {
+            ALOGE("The property: %s is not a supported system property, ignore",
+                  propertyName.c_str());
+            continue;
+        }
+        int requiredVersion = it->second;
+        if (myVersion < requiredVersion) {
+            ALOGE("The property: %s is not supported for current client VHAL version, "
+                  "require %d, current version: %d, ignore",
+                  propertyName.c_str(), requiredVersion, myVersion);
+            continue;
+        }
+        filteredConfigs.push_back(std::move(config));
+    }
+    for (auto& config : filteredConfigs) {
         mConfigsByPropId[config.prop] = config;
     }
     VehiclePropConfigs vehiclePropConfigs;
-    vehiclePropConfigs.payloads = std::move(configs);
+    vehiclePropConfigs.payloads = std::move(filteredConfigs);
     auto result = LargeParcelableBase::parcelableToStableLargeParcelable(vehiclePropConfigs);
     if (!result.ok()) {
         ALOGE("failed to convert configs to shared memory file, error: %s, code: %d",
@@ -413,9 +453,9 @@
                     .status = getErrorCode(result),
                     .prop = {},
             });
-        } else {
-            hardwareRequests.push_back(request);
+            continue;
         }
+        hardwareRequests.push_back(request);
     }
 
     // The set of request Ids that we would send to hardware.
@@ -816,6 +856,7 @@
     if (!result.ok()) {
         return StatusError(StatusCode::INVALID_ARG) << getErrorMsg(result);
     }
+
     const VehiclePropConfig* config = result.value();
     const VehicleAreaConfig* areaConfig = getAreaConfig(value, *config);
 
@@ -900,6 +941,7 @@
     dprintf(fd, "Vehicle HAL State: \n");
     {
         std::scoped_lock<std::mutex> lockGuard(mLock);
+        dprintf(fd, "Interface version: %" PRId32 "\n", getVhalInterfaceVersion());
         dprintf(fd, "Containing %zu property configs\n", mConfigsByPropId.size());
         dprintf(fd, "Currently have %zu getValues clients\n", mGetValuesClients.size());
         dprintf(fd, "Currently have %zu setValues clients\n", mSetValuesClients.size());
diff --git a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
index a63cb84..bb82108 100644
--- a/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
+++ b/automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp
@@ -79,36 +79,37 @@
 using ::ndk::SpAIBinder;
 
 using ::testing::ContainsRegex;
+using ::testing::ElementsAre;
 using ::testing::Eq;
 using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
 using ::testing::WhenSortedBy;
 
 constexpr int32_t INVALID_PROP_ID = 0;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x10000000 + 0x03000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t READ_ONLY_PROP = 10006 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_CONTINUOUS_PROP_NO_VUR = 10008 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
-constexpr int32_t GLOBAL_NONE_ACCESS_PROP = 10009 + 0x10000000 + 0x01000000 + 0x00400000;
-// VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32
-constexpr int32_t AREA_NONE_ACCESS_PROP = 10010 + 0x10000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_ON_CHANGE_PROP = 10002 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_CONTINUOUS_PROP = 10003 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_ON_CHANGE_PROP = 10004 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_CONTINUOUS_PROP = 10005 + 0x20000000 + 0x03000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t READ_ONLY_PROP = 10006 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t WRITE_ONLY_PROP = 10007 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_CONTINUOUS_PROP_NO_VUR = 10008 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+constexpr int32_t GLOBAL_NONE_ACCESS_PROP = 10009 + 0x20000000 + 0x01000000 + 0x00400000;
+// VehiclePropertyGroup:VENDOR,VehicleArea:WINDOW,VehiclePropertyType:INT32
+constexpr int32_t AREA_NONE_ACCESS_PROP = 10010 + 0x20000000 + 0x03000000 + 0x00400000;
 
 int32_t testInt32VecProp(size_t i) {
-    // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
-    return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000;
+    // VehiclePropertyGroup:VENDOR,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
+    return static_cast<int32_t>(i) + 0x20000000 + 0x01000000 + 0x00410000;
 }
 
 std::string toString(const std::vector<SubscribeOptions>& options) {
@@ -556,10 +557,10 @@
 TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsSmall) {
     auto testConfigs = std::vector<VehiclePropConfig>({
             VehiclePropConfig{
-                    .prop = 1,
+                    .prop = testInt32VecProp(1),
             },
             VehiclePropConfig{
-                    .prop = 2,
+                    .prop = testInt32VecProp(2),
             },
     });
 
@@ -580,7 +581,7 @@
     // 5000 VehiclePropConfig exceeds 4k memory limit, so it would be sent through shared memory.
     for (size_t i = 0; i < 5000; i++) {
         testConfigs.push_back(VehiclePropConfig{
-                .prop = static_cast<int32_t>(i),
+                .prop = testInt32VecProp(i),
         });
     }
 
@@ -600,13 +601,42 @@
     ASSERT_EQ(result.value().getObject()->payloads, testConfigs);
 }
 
+TEST_F(DefaultVehicleHalTest, testGetAllPropConfigsFilterOutUnsupportedPropIdsForThisVersion) {
+    auto testConfigs = std::vector<VehiclePropConfig>({
+            // This is supported from V2.
+            VehiclePropConfig{
+                    .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+            },
+            // This is supported from V3
+            VehiclePropConfig{
+                    .prop = toInt(VehicleProperty::ULTRASONICS_SENSOR_POSITION),
+            },
+    });
+
+    auto hardware = std::make_unique<MockVehicleHardware>();
+    hardware->setPropertyConfigs(testConfigs);
+    auto vhal = ndk::SharedRefBase::make<DefaultVehicleHal>(std::move(hardware),
+                                                            /* testInterfaceVersion= */ 2);
+    std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
+
+    VehiclePropConfigs output;
+    auto status = client->getAllPropConfigs(&output);
+
+    ASSERT_TRUE(status.isOk()) << "getAllPropConfigs failed: " << status.getMessage();
+    ASSERT_THAT(output.payloads, ElementsAre(VehiclePropConfig{
+                                         .prop = toInt(VehicleProperty::PERF_VEHICLE_SPEED),
+                                 }));
+}
+
 TEST_F(DefaultVehicleHalTest, testGetPropConfigs) {
+    int32_t propId1 = testInt32VecProp(1);
+    int32_t propId2 = testInt32VecProp(2);
     auto testConfigs = std::vector<VehiclePropConfig>({
             VehiclePropConfig{
-                    .prop = 1,
+                    .prop = propId1,
             },
             VehiclePropConfig{
-                    .prop = 2,
+                    .prop = propId2,
             },
     });
 
@@ -616,7 +646,7 @@
     std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
 
     VehiclePropConfigs output;
-    auto status = client->getPropConfigs(std::vector<int32_t>({1, 2}), &output);
+    auto status = client->getPropConfigs(std::vector<int32_t>({propId1, propId2}), &output);
 
     ASSERT_TRUE(status.isOk()) << "getPropConfigs failed: " << status.getMessage();
     ASSERT_EQ(output.payloads, testConfigs);
@@ -625,10 +655,10 @@
 TEST_F(DefaultVehicleHalTest, testGetPropConfigsInvalidArg) {
     auto testConfigs = std::vector<VehiclePropConfig>({
             VehiclePropConfig{
-                    .prop = 1,
+                    .prop = testInt32VecProp(1),
             },
             VehiclePropConfig{
-                    .prop = 2,
+                    .prop = testInt32VecProp(2),
             },
     });
 
@@ -638,7 +668,9 @@
     std::shared_ptr<IVehicle> client = IVehicle::fromBinder(vhal->asBinder());
 
     VehiclePropConfigs output;
-    auto status = client->getPropConfigs(std::vector<int32_t>({1, 2, 3}), &output);
+    auto status = client->getPropConfigs(
+            std::vector<int32_t>({testInt32VecProp(1), testInt32VecProp(2), testInt32VecProp(3)}),
+            &output);
 
     ASSERT_FALSE(status.isOk()) << "getPropConfigs must fail with invalid prop ID";
     ASSERT_EQ(status.getServiceSpecificError(), toInt(StatusCode::INVALID_ARG));