1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.car.cluster.sensors; 17 18 import android.car.VehiclePropertyIds; 19 import android.car.VehiclePropertyType; 20 import android.car.hardware.CarPropertyValue; 21 import android.car.hardware.CarSensorEvent; 22 23 import java.util.ArrayList; 24 import java.util.HashMap; 25 import java.util.List; 26 import java.util.Map; 27 import java.util.Set; 28 import java.util.function.Function; 29 30 /** 31 * The collection of all sensors supported by this application. 32 */ 33 public class Sensors { 34 /** Area identifier used for sensors corresponding to global VHAL properties */ 35 public static final int GLOBAL_AREA_ID = -1; 36 37 private static Sensors sInstance; 38 private static List<Sensor<?>> sSensors = new ArrayList<>(); 39 private Map<Integer, List<Sensor<?>>> mSensorsByPropertyId = new HashMap<>(); 40 41 /** Possible values of the {@link #SENSOR_GEAR} sensor */ 42 public enum Gear { 43 NEUTRAL, 44 REVERSE, 45 DRIVE, 46 PARK, 47 } 48 49 /** Fuel of the car, measured in millimeters */ 50 public static final Sensor<Float> SENSOR_FUEL = registerSensor( 51 "Fuel", VehiclePropertyIds.FUEL_LEVEL, GLOBAL_AREA_ID, VehiclePropertyType.FLOAT, 52 value -> (Float) value.getValue()); 53 /** Fuel capacity of the car, measured in millimeters */ 54 public static final Sensor<Float> SENSOR_FUEL_CAPACITY = registerSensor( 55 "Fuel Capacity", VehiclePropertyIds.INFO_FUEL_CAPACITY, GLOBAL_AREA_ID, 56 VehiclePropertyType.FLOAT, 57 value -> (Float) value.getValue()); 58 /** RPMs */ 59 public static final Sensor<Float> SENSOR_RPM = registerSensor( 60 "RPM", VehiclePropertyIds.ENGINE_RPM, GLOBAL_AREA_ID, 61 VehiclePropertyType.FLOAT, 62 value -> (Float) value.getValue()); 63 /** Fuel range in meters */ 64 public static final Sensor<Float> SENSOR_FUEL_RANGE = registerSensor( 65 "Fuel Range", VehiclePropertyIds.RANGE_REMAINING, GLOBAL_AREA_ID, 66 VehiclePropertyType.FLOAT, 67 value -> (Float) value.getValue()); 68 /** Speed in meters per second */ 69 public static final Sensor<Float> SENSOR_SPEED = registerSensor( 70 "Speed", VehiclePropertyIds.PERF_VEHICLE_SPEED, GLOBAL_AREA_ID, 71 VehiclePropertyType.FLOAT, 72 value -> (Float) value.getValue()); 73 /** Current gear of the car */ 74 public static final Sensor<Gear> SENSOR_GEAR = registerSensor( 75 "Gear", VehiclePropertyIds.GEAR_SELECTION, GLOBAL_AREA_ID, VehiclePropertyType.INT32, 76 value -> { 77 if (value == null) { 78 return null; 79 } 80 Integer gear = (Integer) value.getValue(); 81 if ((gear & CarSensorEvent.GEAR_REVERSE) != 0) { 82 return Gear.REVERSE; 83 } else if ((gear & CarSensorEvent.GEAR_NEUTRAL) != 0) { 84 return Gear.NEUTRAL; 85 } else if ((gear & CarSensorEvent.GEAR_DRIVE) != 0) { 86 return Gear.DRIVE; 87 } else if ((gear & CarSensorEvent.GEAR_PARK) != 0) { 88 return Gear.PARK; 89 } else { 90 return null; 91 } 92 }); 93 registerSensor(String propertyName, int propertyId, int areaId, int expectedPropertyType, Function<CarPropertyValue<?>, T> adapter)94 private static <T> Sensor<T> registerSensor(String propertyName, int propertyId, int areaId, 95 int expectedPropertyType, Function<CarPropertyValue<?>, T> adapter) { 96 Sensor<T> sensor = new Sensor<>(propertyName, propertyId, areaId, expectedPropertyType, 97 adapter); 98 sSensors.add(sensor); 99 return sensor; 100 } 101 102 /** 103 * Obtains the singleton instance of this class 104 */ getInstance()105 public static Sensors getInstance() { 106 if (sInstance == null) { 107 sInstance = new Sensors(); 108 } 109 return sInstance; 110 } 111 Sensors()112 private Sensors() { 113 initializeSensorsMap(); 114 } 115 initializeSensorsMap()116 private void initializeSensorsMap() { 117 for (Sensor<?> sensorId : getSensors()) { 118 mSensorsByPropertyId 119 .computeIfAbsent(sensorId.mPropertyId, (id) -> new ArrayList<>()) 120 .add(sensorId); 121 } 122 } 123 124 /** 125 * Returns all sensors. 126 */ getSensors()127 public List<Sensor<?>> getSensors() { 128 return sSensors; 129 } 130 131 /** 132 * Returns all sensors associated to the given VHAL property id. 133 */ getSensorsForPropertyId(int propertyId)134 public List<Sensor<?>> getSensorsForPropertyId(int propertyId) { 135 return mSensorsByPropertyId.get(propertyId); 136 } 137 138 /** 139 * Returns all property ids we care about. 140 */ getPropertyIds()141 public Set<Integer> getPropertyIds() { 142 return mSensorsByPropertyId.keySet(); 143 } 144 } 145