1 /* 2 * Copyright (C) 2019 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 com.android.car.settings.units; 18 19 import android.car.Car; 20 import android.car.CarNotConnectedException; 21 import android.car.VehiclePropertyIds; 22 import android.car.VehicleUnit; 23 import android.car.feature.Flags; 24 import android.car.hardware.CarPropertyConfig; 25 import android.car.hardware.property.CarPropertyManager; 26 import android.content.Context; 27 import android.util.ArraySet; 28 29 import com.android.car.settings.common.Logger; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 34 /** Utility to read and write {@link Unit}-related properties in {@link CarPropertyManager}. */ 35 public class CarUnitsManager { 36 private static final Logger LOG = new Logger(CarUnitsManager.class); 37 private static final int AREA_ID = 0; 38 39 private Context mContext; 40 private Car mCar; 41 private CarPropertyManager mCarPropertyManager; 42 private OnCarServiceListener mCarServiceListener; 43 CarUnitsManager(Context context)44 public CarUnitsManager(Context context) { 45 mContext = context; 46 mCar = Car.createCar(mContext); 47 mCarPropertyManager = 48 (CarPropertyManager) mCar.getCarManager(Car.PROPERTY_SERVICE); 49 } 50 51 /** 52 * Registers {@link OnCarServiceListener} as a Callback for when connection to {@link Car} has 53 * been established. 54 */ registerCarServiceListener(OnCarServiceListener listener)55 public void registerCarServiceListener(OnCarServiceListener listener) { 56 mCarServiceListener = listener; 57 mCarServiceListener.handleServiceConnected(mCarPropertyManager); 58 } 59 60 /** 61 * Unregisters {@link OnCarServiceListener} as a Callback for when connection to {@link Car} has 62 * been terminated. 63 */ unregisterCarServiceListener()64 public void unregisterCarServiceListener() { 65 mCarServiceListener = null; 66 } 67 disconnect()68 protected void disconnect() { 69 mCar.disconnect(); 70 if (mCarServiceListener != null) { 71 mCarServiceListener.handleServiceDisconnected(); 72 } 73 } 74 isPropertyAvailable(int propertyId)75 protected boolean isPropertyAvailable(int propertyId) { 76 Integer intProperty = null; 77 78 try { 79 intProperty = mCarPropertyManager.getIntProperty(propertyId, AREA_ID); 80 } catch (CarNotConnectedException e) { 81 LOG.e("Property is unavailable because Car is not connected."); 82 } 83 84 return intProperty != null && intProperty != VehicleUnit.SHOULD_NOT_USE; 85 } 86 getUnitsSupportedByProperty(int propertyId)87 protected Unit[] getUnitsSupportedByProperty(int propertyId) { 88 ArraySet<Integer> propertyIdSet = new ArraySet<Integer>(); 89 propertyIdSet.add(propertyId); 90 List<CarPropertyConfig> configs = mCarPropertyManager.getPropertyList(propertyIdSet); 91 List<Integer> availableUnitsId = new ArrayList<Integer>(); 92 List<Unit> units = new ArrayList<Unit>(); 93 94 if (configs == null || configs.size() < 1 || configs.get(0) == null) { 95 return null; 96 } 97 98 // Checks if the property is read-write property. Checking only one area Id because _UNITS 99 // properties are global properties. 100 if ((Flags.areaIdConfigAccess() ? configs.get(0).getAreaIdConfig(0).getAccess() 101 : configs.get(0).getAccess()) 102 != CarPropertyConfig.VEHICLE_PROPERTY_ACCESS_READ_WRITE) { 103 return null; 104 } 105 106 availableUnitsId = configs.get(0).getConfigArray(); 107 108 Unit[] result = new Unit[availableUnitsId.size()]; 109 for (int unitId : availableUnitsId) { 110 if (UnitsMap.MAP.get(unitId) != null) { 111 Unit unit = UnitsMap.MAP.get(unitId); 112 units.add(unit); 113 } 114 } 115 for (int i = 0; i < result.length; i++) { 116 int unitId = availableUnitsId.get(i); 117 if (UnitsMap.MAP.get(unitId) != null) { 118 Unit unit = UnitsMap.MAP.get(unitId); 119 result[i] = unit; 120 } 121 } 122 return result; 123 } 124 getUnitUsedByProperty(int propertyId)125 protected Unit getUnitUsedByProperty(int propertyId) { 126 try { 127 int unitId = mCarPropertyManager.getIntProperty(propertyId, AREA_ID); 128 if (UnitsMap.MAP.get(unitId) != null) { 129 return UnitsMap.MAP.get(unitId); 130 } else { 131 return null; 132 } 133 } catch (CarNotConnectedException e) { 134 LOG.e("CarPropertyManager cannot get property because Car is not connected."); 135 return null; 136 } 137 } 138 setUnitUsedByProperty(int propertyId, int unitId)139 protected void setUnitUsedByProperty(int propertyId, int unitId) { 140 try { 141 mCarPropertyManager.setIntProperty(propertyId, AREA_ID, unitId); 142 } catch (CarNotConnectedException e) { 143 LOG.e("CarPropertyManager cannot set property because Car is not connected."); 144 } 145 } 146 147 /** 148 * Returns a boolean that indicates whether the unit is expressed in distance per volume (true) 149 * or volume per distance (false) for fuel consumption. Note that only distance over volume 150 * format is supported when Mile and Gallon (both US and UK) units are used. 151 */ isDistanceOverVolume()152 protected boolean isDistanceOverVolume() { 153 try { 154 return mCarPropertyManager.getBooleanProperty( 155 VehiclePropertyIds.FUEL_CONSUMPTION_UNITS_DISTANCE_OVER_VOLUME, AREA_ID); 156 } catch (CarNotConnectedException e) { 157 return true; // Defaults to True. 158 } 159 } 160 161 /** Defines callbacks that listen to {@link Car} service-related events. */ 162 public interface OnCarServiceListener { 163 /** 164 * Callback to be run when {@link Car} service is connected and {@link 165 * CarPropertyManager} becomes available. 166 */ handleServiceConnected(CarPropertyManager carPropertyManager)167 void handleServiceConnected(CarPropertyManager carPropertyManager); 168 169 /** Callback to be run when {@link Car} service is disconnected. */ handleServiceDisconnected()170 void handleServiceDisconnected(); 171 } 172 } 173