Support VHAL 2.1 in Car Service

Bug: b/34716856

Test: manual
Change-Id: I6c5f83fc097dcc373fb3a97a4c57f9c143a73a70
diff --git a/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java b/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
index aeb25a0..8371463 100644
--- a/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
+++ b/car-lib/src_feature_current/com/android/car/internal/FeatureConfiguration.java
@@ -27,4 +27,5 @@
     public static final boolean ENABLE_PRODUCT_CONFIGURATION_INFO = DEFAULT;
     public static final boolean ENABLE_VEHICLE_MAP_SERVICE = DEFAULT;
     public static final boolean ENABLE_DIAGNOSTIC = DEFAULT;
+    public static final boolean ENABLE_VEHICLE_HAL_V2_1 = DEFAULT;
 }
diff --git a/car-lib/src_feature_future/com/android/car/internal/FeatureConfiguration.java b/car-lib/src_feature_future/com/android/car/internal/FeatureConfiguration.java
index f7b5c9f..62bfd06 100644
--- a/car-lib/src_feature_future/com/android/car/internal/FeatureConfiguration.java
+++ b/car-lib/src_feature_future/com/android/car/internal/FeatureConfiguration.java
@@ -27,4 +27,5 @@
     public static final boolean ENABLE_PRODUCT_CONFIGURATION_INFO = DEFAULT;
     public static final boolean ENABLE_VEHICLE_MAP_SERVICE = DEFAULT;
     public static final boolean ENABLE_DIAGNOSTIC = DEFAULT;
+    public static final boolean ENABLE_VEHICLE_HAL_V2_1 = DEFAULT;
 }
diff --git a/car_product/build/car_base.mk b/car_product/build/car_base.mk
index eb3145b..6544dc1 100644
--- a/car_product/build/car_base.mk
+++ b/car_product/build/car_base.mk
@@ -81,7 +81,12 @@
     requestsync \
     wifi-service \
     A2dpSinkService \
-    android.hardware.automotive.vehicle@2.0-service \
+
+ifeq ($(TARGET_USES_CAR_FUTURE_FEATURES),true)
+PRODUCT_PACKAGES += android.hardware.automotive.vehicle@2.1-service
+else
+PRODUCT_PACKAGES += android.hardware.automotive.vehicle@2.0-service
+endif
 
 $(call inherit-product, $(SRC_TARGET_DIR)/product/core_minimal.mk)
 
diff --git a/service/Android.mk b/service/Android.mk
index 4ba2dbd..835b2bc 100644
--- a/service/Android.mk
+++ b/service/Android.mk
@@ -44,6 +44,7 @@
 LOCAL_JAVA_LIBRARIES += android.car
 LOCAL_STATIC_JAVA_LIBRARIES += \
         android.hardware.automotive.vehicle@2.0-java-static \
+        android.hardware.automotive.vehicle@2.1-java-static \
         vehicle-hal-support-lib \
         car-systemtest \
 
@@ -64,6 +65,7 @@
 LOCAL_JAVA_LIBRARIES += android.car
 LOCAL_STATIC_JAVA_LIBRARIES += \
         android.hardware.automotive.vehicle@2.0-java-static \
+        android.hardware.automotive.vehicle@2.1-java-static \
         vehicle-hal-support-lib \
         car-systemtest \
 
diff --git a/service/src/com/android/car/CarService.java b/service/src/com/android/car/CarService.java
index d230495..bc91f0e 100644
--- a/service/src/com/android/car/CarService.java
+++ b/service/src/com/android/car/CarService.java
@@ -16,6 +16,7 @@
 package com.android.car;
 
 import static android.os.SystemClock.elapsedRealtime;
+import static com.android.car.internal.FeatureConfiguration.ENABLE_VEHICLE_HAL_V2_1;
 
 import android.annotation.Nullable;
 import android.app.Service;
@@ -47,10 +48,17 @@
 
     private static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
 
+    private static final String IVHAL_20 =
+            android.hardware.automotive.vehicle.V2_0.IVehicle.kInterfaceName;
+    private static final String IVHAL_21 =
+            android.hardware.automotive.vehicle.V2_1.IVehicle.kInterfaceName;
+
     private CanBusErrorNotifier mCanBusErrorNotifier;
     private ICarImpl mICarImpl;
     private IVehicle mVehicle;
 
+    private String mVehicleInterfaceName;
+
     // If 10 crashes of Vehicle HAL occurred within 10 minutes then thrown an exception in
     // Car Service.
     private final CrashTracker mVhalCrashTracker = new CrashTracker(
@@ -73,10 +81,18 @@
     public void onCreate() {
         Log.i(CarLog.TAG_SERVICE, "Service onCreate");
         mCanBusErrorNotifier = new CanBusErrorNotifier(this /* context */);
-        mVehicle = getVehicleWithTimeout(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS);
+        mVehicle = getVehicle(null /* Any Vehicle HAL interface name */);
+
         if (mVehicle == null) {
             throw new IllegalStateException("Vehicle HAL service is not available.");
         }
+        try {
+            mVehicleInterfaceName = mVehicle.interfaceDescriptor();
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Unable to get Vehicle HAL interface descriptor", e);
+        }
+
+        Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
 
         mICarImpl = new ICarImpl(this, mVehicle, SystemInterface.getDefault(this),
                 mCanBusErrorNotifier);
@@ -128,6 +144,7 @@
         }
         if (args == null || args.length == 0) {
             writer.println("*dump car service*");
+            writer.println("Vehicle HAL Interface: " + mVehicleInterfaceName);
             mICarImpl.dump(writer);
 
             writer.println("**Debug info**");
@@ -139,8 +156,8 @@
     }
 
     @Nullable
-    private IVehicle getVehicleWithTimeout(long waitMilliseconds) {
-        IVehicle vehicle = getVehicle();
+    private IVehicle getVehicleWithTimeout(long waitMilliseconds, @Nullable String interfaceName) {
+        IVehicle vehicle = getVehicle(interfaceName);
         long start = elapsedRealtime();
         while (vehicle == null && (start + waitMilliseconds) > elapsedRealtime()) {
             try {
@@ -149,7 +166,7 @@
                 throw new RuntimeException("Sleep was interrupted", e);
             }
 
-            vehicle = getVehicle();
+            vehicle = getVehicle(interfaceName);
         }
 
         if (vehicle != null) {
@@ -160,9 +177,20 @@
     }
 
     @Nullable
-    private IVehicle getVehicle() {
+    private static IVehicle getVehicle(@Nullable String interfaceName) {
         try {
-            return IVehicle.getService(VEHICLE_SERVICE_NAME);
+            boolean anyVersion = interfaceName == null || interfaceName.isEmpty();
+            IVehicle vehicle = null;
+            if (ENABLE_VEHICLE_HAL_V2_1 && (anyVersion || IVHAL_21.equals(interfaceName))) {
+                vehicle = android.hardware.automotive.vehicle.V2_1.IVehicle
+                        .getService(VEHICLE_SERVICE_NAME);
+            }
+
+            if (vehicle == null && (anyVersion || IVHAL_20.equals(interfaceName))) {
+                vehicle = android.hardware.automotive.vehicle.V2_0.IVehicle
+                        .getService(VEHICLE_SERVICE_NAME);
+            }
+            return vehicle;
         } catch (RemoteException e) {
             Log.e(CarLog.TAG_SERVICE, "Failed to get IVehicle service", e);
         } catch (NoSuchElementException e) {
@@ -187,8 +215,10 @@
 
             mVhalCrashTracker.crashDetected();
 
-            Log.i(CarLog.TAG_SERVICE, "Trying to reconnect to Vehicle HAL...");
-            mVehicle = getVehicleWithTimeout(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS);
+            Log.i(CarLog.TAG_SERVICE, "Trying to reconnect to Vehicle HAL: " +
+                    mVehicleInterfaceName);
+            mVehicle = getVehicleWithTimeout(WAIT_FOR_VEHICLE_HAL_TIMEOUT_MS,
+                    mVehicleInterfaceName);
             if (mVehicle == null) {
                 throw new IllegalStateException("Failed to reconnect to Vehicle HAL");
             }