Dump VMS HAL client stats obtained by reading a vendor property.
Bug: 139153868
Test: Added new unit tests to VmsHalServiceTest
Test: atest AndroidCarApiTest CarServiceTest CarServiceUnitTest
Change-Id: I97fcd730c7433ea6753719207d967e119bcc6a4f
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index 95383dc..370fe5d 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -78,6 +78,8 @@
</string-array>
<!-- Default home activity -->
<string name="defaultHomeActivity" translatable="false"><!--com.your.package/com.your.package.Activity--></string>
+ <!-- The vendor-defined HAL property used to collect VMS client metrics. Disabled by default.-->
+ <integer name="vmsHalClientMetricsProperty">0</integer>
<!-- The com.android.car.vms.VmsClientManager will bind to this list of clients running as system user -->
<string-array translatable="false" name="vmsPublisherSystemClients">
</string-array>
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index 5c170d9..8527208 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -118,7 +118,7 @@
CanBusErrorNotifier errorNotifier, String vehicleInterfaceName) {
mContext = serviceContext;
mSystemInterface = systemInterface;
- mHal = new VehicleHal(vehicle);
+ mHal = new VehicleHal(serviceContext, vehicle);
mVehicleInterfaceName = vehicleInterfaceName;
mUserManagerHelper = new CarUserManagerHelper(serviceContext);
final Resources res = mContext.getResources();
@@ -473,6 +473,8 @@
} else if ("--metrics".equals(args[0])) {
writer.println("*Dump car service metrics*");
dumpAllServices(writer, true);
+ } else if ("--vms-hal".equals(args[0])) {
+ mHal.getVmsHal().dumpMetrics(fd);
} else if (Build.IS_USERDEBUG || Build.IS_ENG) {
execShellCmd(args, writer);
} else {
diff --git a/service/src/com/android/car/hal/VehicleHal.java b/service/src/com/android/car/hal/VehicleHal.java
index 374ae7b..d85a357 100644
--- a/service/src/com/android/car/hal/VehicleHal.java
+++ b/service/src/com/android/car/hal/VehicleHal.java
@@ -23,6 +23,7 @@
import static java.lang.Integer.toHexString;
import android.annotation.CheckResult;
+import android.content.Context;
import android.hardware.automotive.vehicle.V2_0.IVehicle;
import android.hardware.automotive.vehicle.V2_0.IVehicleCallback;
import android.hardware.automotive.vehicle.V2_0.SubscribeFlags;
@@ -89,14 +90,14 @@
// Used by injectVHALEvent for testing purposes. Delimiter for an array of data
private static final String DATA_DELIMITER = ",";
- public VehicleHal(IVehicle vehicle) {
+ public VehicleHal(Context context, IVehicle vehicle) {
mHandlerThread = new HandlerThread("VEHICLE-HAL");
mHandlerThread.start();
// passing this should be safe as long as it is just kept and not used in constructor
mPowerHal = new PowerHalService(this);
mPropertyHal = new PropertyHalService(this);
mInputHal = new InputHalService(this);
- mVmsHal = new VmsHalService(this);
+ mVmsHal = new VmsHalService(context, this);
mDiagnosticHal = new DiagnosticHalService(this);
mAllServices.addAll(Arrays.asList(mPowerHal,
mInputHal,
diff --git a/service/src/com/android/car/hal/VmsHalService.java b/service/src/com/android/car/hal/VmsHalService.java
index fcf717f..40982c8 100644
--- a/service/src/com/android/car/hal/VmsHalService.java
+++ b/service/src/com/android/car/hal/VmsHalService.java
@@ -31,9 +31,11 @@
import android.car.vms.VmsLayersOffering;
import android.car.vms.VmsOperationRecorder;
import android.car.vms.VmsSubscriptionState;
+import android.content.Context;
import android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
+import android.hardware.automotive.vehicle.V2_0.VehiclePropertyGroup;
import android.hardware.automotive.vehicle.V2_0.VmsBaseMessageIntegerValuesIndex;
import android.hardware.automotive.vehicle.V2_0.VmsMessageType;
import android.hardware.automotive.vehicle.V2_0.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex;
@@ -55,6 +57,9 @@
import com.android.car.CarLog;
import com.android.car.vms.VmsClientManager;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -81,6 +86,7 @@
private final VehicleHal mVehicleHal;
private final int mCoreId;
private final MessageQueue mMessageQueue;
+ private final int mClientMetricsProperty;
private volatile boolean mIsSupported = false;
private VmsClientManager mClientManager;
@@ -192,15 +198,33 @@
/**
* Constructor used by {@link VehicleHal}
*/
- VmsHalService(VehicleHal vehicleHal) {
- this(vehicleHal, SystemClock::uptimeMillis);
+ VmsHalService(Context context, VehicleHal vehicleHal) {
+ this(context, vehicleHal, SystemClock::uptimeMillis);
}
@VisibleForTesting
- VmsHalService(VehicleHal vehicleHal, Supplier<Long> getCoreId) {
+ VmsHalService(Context context, VehicleHal vehicleHal, Supplier<Long> getCoreId) {
mVehicleHal = vehicleHal;
mCoreId = (int) (getCoreId.get() % Integer.MAX_VALUE);
mMessageQueue = new MessageQueue();
+ mClientMetricsProperty = getClientMetricsProperty(context);
+ }
+
+ private static int getClientMetricsProperty(Context context) {
+ int propId = context.getResources().getInteger(
+ com.android.car.R.integer.vmsHalClientMetricsProperty);
+ if (propId == 0) {
+ Log.i(TAG, "Metrics collection disabled");
+ return 0;
+ }
+ if ((propId & VehiclePropertyGroup.MASK) != VehiclePropertyGroup.VENDOR) {
+ Log.w(TAG, String.format("Metrics collection disabled, non-vendor property: 0x%x",
+ propId));
+ return 0;
+ }
+
+ Log.i(TAG, String.format("Metrics collection property: 0x%x", propId));
+ return propId;
}
/**
@@ -289,6 +313,37 @@
}
/**
+ * Dumps HAL client metrics obtained by reading the VMS HAL property.
+ *
+ * @param fd Dumpsys file descriptor to write client metrics to.
+ */
+ public void dumpMetrics(FileDescriptor fd) {
+ if (mClientMetricsProperty == 0) {
+ Log.w(TAG, "Metrics collection is disabled");
+ return;
+ }
+
+ VehiclePropValue vehicleProp = null;
+ try {
+ vehicleProp = mVehicleHal.get(mClientMetricsProperty);
+ } catch (PropertyTimeoutException e) {
+ Log.e(TAG, "Timeout while reading metrics from client");
+ }
+ if (vehicleProp == null) {
+ if (DBG) Log.d(TAG, "Metrics unavailable");
+ return;
+ }
+
+ FileOutputStream fout = new FileOutputStream(fd);
+ try {
+ fout.write(toByteArray(vehicleProp.value.bytes));
+ fout.flush();
+ } catch (IOException e) {
+ Log.e(TAG, "Error writing metrics to output stream");
+ }
+ }
+
+ /**
* Consumes/produces HAL messages.
*
* The format of these messages is defined in: