1 /*
2  * Copyright (C) 2015 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 
17 package android.car;
18 
19 import android.annotation.NonNull;
20 import android.car.annotation.ValueTypeDef;
21 import android.car.hardware.CarPropertyValue;
22 import android.car.hardware.property.CarPropertyManager;
23 import android.car.hardware.property.ICarProperty;
24 import android.os.Bundle;
25 import android.os.IBinder;
26 import android.util.Slog;
27 
28 import java.util.Arrays;
29 
30 
31 /**
32  * Utility to retrieve various static information from car. Each data are grouped as {@link Bundle}
33  * and relevant data can be checked from {@link Bundle} using pre-specified keys.
34  */
35 public final class CarInfoManager extends CarManagerBase {
36 
37     private static final String TAG = CarInfoManager.class.getSimpleName();
38 
39     private final CarPropertyManager mCarPropertyMgr;
40     /**
41      * Key for manufacturer of the car. Passed in basic info Bundle.
42      * @hide
43      */
44     @ValueTypeDef(type = Integer.class)
45     public static final int BASIC_INFO_KEY_MANUFACTURER = 0x11100101;
46     /**
47      * Key for model name of the car. This information may not necessarily allow distinguishing
48      * different car models as the same name may be used for different cars depending on
49      * manufacturers. Passed in basic info Bundle.
50      * @hide
51      */
52     @ValueTypeDef(type = Integer.class)
53     public static final int BASIC_INFO_KEY_MODEL = 0x11100102;
54     /**
55      * Key for model year of the car in AD. Passed in basic info Bundle.
56      * @hide
57      */
58     @ValueTypeDef(type = Integer.class)
59     public static final int BASIC_INFO_KEY_MODEL_YEAR = 0x11400103;
60     /**
61      * Key for unique identifier for the car. This is not VIN, and id is persistent until user
62      * resets it. Passed in basic info Bundle.
63      * @hide
64      */
65     @ValueTypeDef(type = String.class)
66     public static final String BASIC_INFO_KEY_VEHICLE_ID = "android.car.vehicle-id";
67     /**
68      * Key for product configuration info.
69      * @hide
70      */
71     @ValueTypeDef(type = String.class)
72     public static final String INFO_KEY_PRODUCT_CONFIGURATION = "android.car.product-config";
73     /**
74      * Key for driver seat of the car.
75      * @hide
76      */
77     @ValueTypeDef(type = Integer.class)
78     public static final int BASIC_INFO_DRIVER_SEAT = 0x1540010a;
79     /**
80      * Key for EV port location of vehicle.
81      * @hide
82      */
83     @ValueTypeDef(type = Integer.class)
84     public static final int BASIC_INFO_EV_PORT_LOCATION = 0x11400109;
85     /**
86      * Key for fuel door location of vehicle.
87      * @hide
88      */
89     @ValueTypeDef(type = Integer.class)
90     public static final int BASIC_INFO_FUEL_DOOR_LOCATION = 0x11400108;
91     /**
92      * Key for Fuel Capacity in milliliters.  Passed in basic info Bundle.
93      * @hide
94      */
95     @ValueTypeDef(type = Integer.class)
96     public static final int BASIC_INFO_FUEL_CAPACITY = 0x11600104;
97     /**
98      * Key for Fuel Types.  This is an array of fuel types the vehicle supports.
99      * Passed in basic info Bundle.
100      * @hide
101      */
102     @ValueTypeDef(type = Integer.class)
103     public static final int BASIC_INFO_FUEL_TYPES = 0x11410105;
104     /**
105      * Key for EV Battery Capacity in WH.  Passed in basic info Bundle.
106      * @hide
107      */
108     @ValueTypeDef(type = Integer.class)
109     public static final int BASIC_INFO_EV_BATTERY_CAPACITY = 0x11600106;
110     /**
111      * Key for EV Connector Types.  This is an array of connector types the vehicle supports.
112      * Passed in basic info Bundle.
113      * @hide
114      */
115     @ValueTypeDef(type = Integer[].class)
116     public static final int BASIC_INFO_EV_CONNECTOR_TYPES = 0x11410107;
117 
118     /**
119      * @return Manufacturer of the car.  Empty if not available.
120      */
121     @NonNull
getManufacturer()122     public String getManufacturer() {
123         return  getPropertyWithDefaultValue(String.class, BASIC_INFO_KEY_MANUFACTURER, "");
124     }
125 
126     /**
127      * @return Model name of the car, empty if not available.  This information
128      * may not necessarily allow distinguishing different car models as the same
129      * name may be used for different cars depending on manufacturers.
130      */
131     @NonNull
getModel()132     public String getModel() {
133         return getPropertyWithDefaultValue(String.class, BASIC_INFO_KEY_MODEL, "");
134     }
135 
136     /**
137      * @return Model year of the car in AD.  Empty if not available.
138      * @deprecated Use {@link #getModelYearInInteger()} instead.
139      */
140     @Deprecated
141     @NonNull
getModelYear()142     public String getModelYear() {
143         int year =  getModelYearInInteger();
144         return year == 0 ? "" : Integer.toString(year);
145     }
146 
147     /**
148      * @return Model year of the car in AD.  0 if not available.
149      */
getModelYearInInteger()150     public int getModelYearInInteger() {
151         return getPropertyWithDefaultValue(Integer.class, BASIC_INFO_KEY_MODEL_YEAR, 0);
152     }
153 
154     /**
155      * @return always return empty string.
156      * @deprecated no support for car's identifier
157      */
158     @Deprecated
getVehicleId()159     public String getVehicleId() {
160         return "";
161     }
162 
163     /**
164      * @return Fuel capacity of the car in milliliters.  0 if car doesn't run on
165      *         fuel.
166      */
getFuelCapacity()167     public float getFuelCapacity() {
168         return getPropertyWithDefaultValue(Float.class, BASIC_INFO_FUEL_CAPACITY, 0f);
169     }
170 
171     /**
172      * @return Array of FUEL_TYPEs available in the car.  Empty array if no fuel
173      * types available.
174      */
getFuelTypes()175     public @FuelType.Enum int[] getFuelTypes() {
176         Integer[] fuels = getPropertyWithDefaultValue(Integer[].class, BASIC_INFO_FUEL_TYPES,
177                 new Integer[]{});
178         return Arrays.stream(fuels).mapToInt(Integer::intValue).toArray();
179     }
180 
181     /**
182      *
183      * @return Battery capacity of the car in Watt-Hour(Wh). Return 0 if car doesn't run on battery.
184      */
getEvBatteryCapacity()185     public float getEvBatteryCapacity() {
186         return getPropertyWithDefaultValue(Float.class, BASIC_INFO_EV_BATTERY_CAPACITY, 0f);
187     }
188 
189     /**
190      * @return Array of EV_CONNECTOR_TYPEs available in the car.  Empty array if
191      *         no connector types available.
192      */
getEvConnectorTypes()193     public @EvConnectorType.Enum int[] getEvConnectorTypes() {
194         Integer[] valueInHal = getPropertyWithDefaultValue(Integer[].class,
195                 BASIC_INFO_EV_CONNECTOR_TYPES, new Integer[]{});
196 
197         int[] connectorTypes = new int[valueInHal.length];
198         for (int i = 0; i < valueInHal.length; i++) {
199             switch (valueInHal[i]) {
200                 case 1: // IEC_TYPE_1_AC
201                     connectorTypes[i] = EvConnectorType.J1772;
202                     break;
203                 case 2: // IEC_TYPE_2_AC
204                     connectorTypes[i] = EvConnectorType.MENNEKES;
205                     break;
206                 case 3: // IEC_TYPE_3_AC
207                     connectorTypes[i] = EvConnectorType.SCAME;
208                     break;
209                 case 4: // IEC_TYPE_4_DC
210                     connectorTypes[i] = EvConnectorType.CHADEMO;
211                     break;
212                 case 5: // IEC_TYPE_1_CCS_DC
213                     connectorTypes[i] = EvConnectorType.COMBO_1;
214                     break;
215                 case 6: // IEC_TYPE_2_CCS_DC
216                     connectorTypes[i] = EvConnectorType.COMBO_2;
217                     break;
218                 case 7: // TESLA_ROADSTER
219                     connectorTypes[i] = EvConnectorType.TESLA_ROADSTER;
220                     break;
221                 case 8: // TESLA_HPWC
222                     connectorTypes[i] = EvConnectorType.TESLA_HPWC;
223                     break;
224                 case 9: // TESLA_SUPERCHARGER
225                     connectorTypes[i] = EvConnectorType.TESLA_SUPERCHARGER;
226                     break;
227                 case 10: // GBT_AC
228                     connectorTypes[i] = EvConnectorType.GBT;
229                     break;
230                 case 11: // GBT_DC
231                     connectorTypes[i] = EvConnectorType.GBT_DC;
232                     break;
233                 case 101: // OTHER
234                     connectorTypes[i] = EvConnectorType.OTHER;
235                     break;
236                 default:
237                     connectorTypes[i] = EvConnectorType.UNKNOWN;
238             }
239         }
240         return connectorTypes;
241     }
242 
243     /**
244      * @return Driver seat's location. Returns {@link VehicleAreaSeat#SEAT_UNKNOWN} if the sensor
245      * is not available.
246      */
getDriverSeat()247     public @VehicleAreaSeat.Enum int getDriverSeat() {
248         return getPropertyWithDefaultValue(Integer.class, BASIC_INFO_DRIVER_SEAT,
249                 VehicleAreaSeat.SEAT_UNKNOWN);
250     }
251 
252     /**
253      * @return EV port location of the car. Returns {@link PortLocationType#UNKNOWN} if the sensor
254      * is not available.
255      */
getEvPortLocation()256     public @PortLocationType.Enum int getEvPortLocation() {
257         return getPropertyWithDefaultValue(Integer.class, BASIC_INFO_EV_PORT_LOCATION,
258                 PortLocationType.UNKNOWN);
259     }
260 
261     /**
262      * @return Fuel door location of the car.Returns {@link PortLocationType#UNKNOWN} if the sensor
263      * is not available.
264      */
getFuelDoorLocation()265     public @PortLocationType.Enum int getFuelDoorLocation() {
266         return getPropertyWithDefaultValue(Integer.class, BASIC_INFO_FUEL_DOOR_LOCATION,
267                 PortLocationType.UNKNOWN);
268     }
269 
getPropertyWithDefaultValue(Class<T> clazz, int propId, T defaultValue)270     private <T> T getPropertyWithDefaultValue(Class<T> clazz, int propId, T defaultValue) {
271         try {
272             CarPropertyValue<T> carProp = mCarPropertyMgr.getProperty(
273                     clazz, propId, 0);
274             if (carProp != null && carProp.getStatus() == CarPropertyValue.STATUS_AVAILABLE) {
275                 return carProp.getValue();
276             }
277         } catch (Exception e) {
278             Slog.e(TAG, "Failed to get property value for 0x:" + Integer.toHexString(propId)
279                     + " ,returns default value" + defaultValue);
280         }
281         return defaultValue;
282     }
283 
284     /** @hide */
CarInfoManager(Car car, IBinder service)285     public CarInfoManager(Car car, IBinder service) {
286         super(car);
287         ICarProperty mCarPropertyService = ICarProperty.Stub.asInterface(service);
288         mCarPropertyMgr = new CarPropertyManager(car, mCarPropertyService);
289     }
290 
291     /** @hide */
onCarDisconnected()292     public void onCarDisconnected() {
293         mCarPropertyMgr.onCarDisconnected();
294     }
295 }
296