/* * Copyright (C) 2019 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. */ package com.android.car; import android.annotation.Nullable; import android.car.builtin.util.Slogf; import android.car.occupantawareness.DriverMonitoringDetection; import android.car.occupantawareness.GazeDetection; import android.car.occupantawareness.OccupantAwarenessDetection; import android.car.occupantawareness.OccupantAwarenessDetection.ConfidenceLevel; import android.car.occupantawareness.Point3D; import android.car.occupantawareness.SystemStatusEvent; import android.car.occupantawareness.SystemStatusEvent.DetectionTypeFlags; import android.car.occupantawareness.SystemStatusEvent.SystemStatus; import android.hardware.automotive.occupant_awareness.IOccupantAwareness; import android.hardware.automotive.occupant_awareness.OccupantAwarenessStatus; /*package*/ final class OccupantAwarenessUtils { private static final String TAG = CarLog.tagFor(OccupantAwarenessUtils.class); private OccupantAwarenessUtils() {} /** Converts status flags into to a SystemStatusEvent. */ static SystemStatusEvent convertToStatusEvent(int inputDetectionFlags, byte inputStatus) { // Parse the system status from the hardware layer. @SystemStatus int outputStatus = SystemStatusEvent.SYSTEM_STATUS_NOT_READY; switch (inputStatus) { case OccupantAwarenessStatus.READY: outputStatus = SystemStatusEvent.SYSTEM_STATUS_READY; break; case OccupantAwarenessStatus.NOT_SUPPORTED: outputStatus = SystemStatusEvent.SYSTEM_STATUS_NOT_SUPPORTED; break; case OccupantAwarenessStatus.NOT_INITIALIZED: outputStatus = SystemStatusEvent.SYSTEM_STATUS_NOT_READY; break; case OccupantAwarenessStatus.FAILURE: outputStatus = SystemStatusEvent.SYSTEM_STATUS_SYSTEM_FAILURE; break; default: Slogf.e(TAG, "Invalid status code: " + inputStatus); break; } // Parse the detection flags from the hardware layer. @DetectionTypeFlags int outputFlags = SystemStatusEvent.DETECTION_TYPE_NONE; switch (inputDetectionFlags) { case IOccupantAwareness.CAP_NONE: outputFlags = SystemStatusEvent.DETECTION_TYPE_NONE; break; case IOccupantAwareness.CAP_PRESENCE_DETECTION: outputFlags = SystemStatusEvent.DETECTION_TYPE_PRESENCE; break; case IOccupantAwareness.CAP_GAZE_DETECTION: outputFlags = SystemStatusEvent.DETECTION_TYPE_GAZE; break; case IOccupantAwareness.CAP_DRIVER_MONITORING_DETECTION: outputFlags = SystemStatusEvent.DETECTION_TYPE_DRIVER_MONITORING; break; default: Slogf.e(TAG, "Invalid status code: " + inputDetectionFlags); break; } return new SystemStatusEvent(outputStatus, outputFlags); } /** Converts an input confidence to a ConfidenceLevel. */ static @ConfidenceLevel int convertToConfidenceScore( @android.hardware.automotive.occupant_awareness.ConfidenceLevel int inputConfidence) { switch (inputConfidence) { case android.hardware.automotive.occupant_awareness.ConfidenceLevel.MAX: return OccupantAwarenessDetection.CONFIDENCE_LEVEL_MAX; case android.hardware.automotive.occupant_awareness.ConfidenceLevel.HIGH: return OccupantAwarenessDetection.CONFIDENCE_LEVEL_HIGH; case android.hardware.automotive.occupant_awareness.ConfidenceLevel.LOW: return OccupantAwarenessDetection.CONFIDENCE_LEVEL_LOW; case android.hardware.automotive.occupant_awareness.ConfidenceLevel.NONE: default: return OccupantAwarenessDetection.CONFIDENCE_LEVEL_NONE; } } /** * Converts an input point to a Point3D. Returns null if the source vector was null or empty. */ static Point3D convertToPoint3D(@Nullable double[] vector) { if (vector != null && vector.length == 3) { return new Point3D(vector[0], vector[1], vector[2]); } else { return null; } } /** Converts an input timestamp to milliseconds since boot. */ static long convertTimestamp(long inputTimestamp) { return inputTimestamp; } /** * Converts an input @android.hardware.automotive.occupant_awareness.Role to a * VehicleOccupantRole. */ static @OccupantAwarenessDetection.VehicleOccupantRole int convertToRole(int inputRole) { if (inputRole == android.hardware.automotive.occupant_awareness.Role.INVALID || inputRole == android.hardware.automotive.occupant_awareness.Role.UNKNOWN) { return OccupantAwarenessDetection.VEHICLE_OCCUPANT_NONE; } else if (inputRole == android.hardware.automotive.occupant_awareness.Role.ALL_OCCUPANTS) { return OccupantAwarenessDetection.VEHICLE_OCCUPANT_ALL_OCCUPANTS; } int outputRole = OccupantAwarenessDetection.VEHICLE_OCCUPANT_NONE; if ((inputRole & android.hardware.automotive.occupant_awareness.Role.DRIVER) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_DRIVER; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.FRONT_PASSENGER) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_FRONT_PASSENGER; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_2_PASSENGER_LEFT) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_2_PASSENGER_LEFT; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_2_PASSENGER_CENTER) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_2_PASSENGER_CENTER; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_2_PASSENGER_RIGHT) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_2_PASSENGER_RIGHT; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_3_PASSENGER_LEFT) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_3_PASSENGER_LEFT; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_3_PASSENGER_CENTER) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_3_PASSENGER_CENTER; } if ((inputRole & android.hardware.automotive.occupant_awareness.Role.ROW_3_PASSENGER_RIGHT) > 0) { outputRole |= OccupantAwarenessDetection.VEHICLE_OCCUPANT_ROW_3_PASSENGER_RIGHT; } return outputRole; } /** Converts an input detection to a GazeDetection. */ static GazeDetection convertToGazeDetection( android.hardware.automotive.occupant_awareness.GazeDetection inputDetection) { return new GazeDetection( convertToConfidenceScore(inputDetection.gazeConfidence), convertToPoint3D(inputDetection.headPosition), convertToPoint3D(inputDetection.headPosition), convertToPoint3D(inputDetection.headAngleUnitVector), convertToPoint3D(inputDetection.gazeAngleUnitVector), inputDetection.gazeTarget, inputDetection.timeOnTargetMillis); } /** Converts an input detection to a DriverMonitoringDetection. */ static DriverMonitoringDetection convertToDriverMonitoringDetection( android.hardware.automotive.occupant_awareness.DriverMonitoringDetection inputDetection) { return new DriverMonitoringDetection( convertToConfidenceScore(inputDetection.confidenceScore), inputDetection.isLookingOnRoad, inputDetection.gazeDurationMillis); } /** Converts a PresenceDetection to a boolean indicating if an occupant was present. */ static boolean convertToPresence( android.hardware.automotive.occupant_awareness.PresenceDetection inputDetection) { return inputDetection.isOccupantDetected; } /** Converts an OccupantDetection to OccupantAwarenessDetection. */ static OccupantAwarenessDetection convertToDetectionEvent( long timestamp, android.hardware.automotive.occupant_awareness.OccupantDetection inputDetection) { // Populate presence, if data is available for this frame. boolean isPresent = false; if (inputDetection.presenceData != null && inputDetection.presenceData.length > 0) { isPresent = convertToPresence(inputDetection.presenceData[0]); } // Populate gaze, if data is available for this frame. GazeDetection gazeDetection = null; if (inputDetection.gazeData != null && inputDetection.gazeData.length > 0) { gazeDetection = convertToGazeDetection(inputDetection.gazeData[0]); } // Populate driver monitoring, if data is available for this frame. DriverMonitoringDetection driverMonitoringDetection = null; if (inputDetection.attentionData != null && inputDetection.attentionData.length > 0) { driverMonitoringDetection = convertToDriverMonitoringDetection(inputDetection.attentionData[0]); } return new OccupantAwarenessDetection( convertToRole(inputDetection.role), timestamp, isPresent, gazeDetection, driverMonitoringDetection); } }