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 package com.android.car; 17 18 import android.car.CarInfoManager; 19 import android.car.ICarInfo; 20 import android.car.annotation.ValueTypeDef; 21 import android.content.Context; 22 import android.os.Bundle; 23 import android.provider.Settings; 24 25 import com.android.car.hal.InfoHalService; 26 import com.android.car.hal.VehicleHal; 27 28 import java.io.PrintWriter; 29 import java.lang.reflect.Field; 30 import java.util.HashMap; 31 import java.util.Map; 32 33 public class CarInfoService extends ICarInfo.Stub implements CarServiceBase { 34 35 private static final HashMap<String, Class> sKeyValueTypeMap; 36 static { 37 sKeyValueTypeMap = new HashMap<String, Class>(); 38 for (Field f : CarInfoManager.class.getDeclaredFields()) { 39 try { 40 if (f.isAnnotationPresent(ValueTypeDef.class) && f.getType() == String.class) { 41 ValueTypeDef typeDef = f.getAnnotation(ValueTypeDef.class); 42 Class type = typeDef.type(); 43 sKeyValueTypeMap.put((String)f.get(null), type); 44 } 45 } catch (IllegalAccessException e) { 46 //ignore 47 } 48 } 49 } 50 51 private final InfoHalService mInfoHal; 52 private final HashMap<String, Object> mInfoCache = new HashMap<String, Object>(); 53 private final Context mContext; 54 55 public CarInfoService(Context context) { 56 mInfoHal = VehicleHal.getInstance().getInfoHal(); 57 mContext = context; 58 } 59 60 @Override 61 public int[] getInt(String key) { 62 assertType(key, Integer.class); 63 Object o = findFromCache(key); 64 if (o != null) { 65 return (int[])o; 66 } 67 int[] v = mInfoHal.getInt(key); 68 if (v != null) { 69 storeToCache(key, v); 70 } 71 return v; 72 } 73 74 @Override 75 public float[] getFloat(String key) { 76 assertType(key, Float.class); 77 Object o = findFromCache(key); 78 if (o != null) { 79 return (float[])o; 80 } 81 float[] v = mInfoHal.getFloat(key); 82 if (v != null) { 83 storeToCache(key, v); 84 } 85 return v; 86 } 87 88 @Override 89 public long[] getLong(String key) { 90 assertType(key, Long.class); 91 Object o = findFromCache(key); 92 if (o != null) { 93 return (long[])o; 94 } 95 long[] v = mInfoHal.getLong(key); 96 if (v != null) { 97 storeToCache(key, v); 98 } 99 return v; 100 } 101 102 @Override 103 public String getString(String key) { 104 assertType(key, String.class); 105 if (CarInfoManager.KEY_VEHICLE_ID.equals(key)) { // do not show real ID. 106 // never put this into cache as ANDROID_ID can be changed. 107 return Settings.Secure.getString(mContext.getContentResolver(), 108 Settings.Secure.ANDROID_ID); 109 } 110 Object o = findFromCache(key); 111 if (o != null) { 112 return (String)o; 113 } 114 String v = mInfoHal.getString(key); 115 if (v != null) { 116 storeToCache(key, v); 117 } 118 return v; 119 } 120 121 @Override 122 public Bundle getBundle(String key) { 123 // OEM may extend this. 124 return null; 125 } 126 127 @Override 128 public void init() { 129 //nothing to do 130 } 131 132 @Override 133 public synchronized void release() { 134 mInfoCache.clear(); 135 } 136 137 @Override 138 public void dump(PrintWriter writer) { 139 writer.println("*CarInfoService*"); 140 writer.println("***Dump info cache***"); 141 for (Map.Entry<String, Object> entry : mInfoCache.entrySet()) { 142 writer.println(entry.getKey() + ":" + entry.getValue()); 143 } 144 } 145 146 private synchronized Object findFromCache(String key) { 147 return mInfoCache.get(key); 148 } 149 150 private synchronized void storeToCache(String key, Object value) { 151 mInfoCache.put(key, value); 152 } 153 154 private void assertType(String key, Class type) throws IllegalArgumentException { 155 Class expectedType = sKeyValueTypeMap.get(key); 156 if (expectedType == null || !expectedType.equals(type)) { 157 throw new IllegalArgumentException("Given key " + key + " expects type " + 158 expectedType + " while used in method for " + type); 159 } 160 } 161 } 162