| /* |
| * 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.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; |
| import android.util.Slog; |
| |
| /*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: |
| Slog.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: |
| Slog.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); |
| } |
| } |