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