1 /* 2 * Copyright (C) 2016 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.hardware; 18 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.car.VehicleAreaType; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 import android.util.SparseArray; 25 26 import java.lang.reflect.Array; 27 import java.util.ArrayList; 28 import java.util.Collections; 29 import java.util.List; 30 31 /** 32 * Represents general information about car property such as data type and min/max ranges for car 33 * areas (if applicable). This class supposed to be immutable, parcelable and could be passed over. 34 * 35 * <p>Use {@link CarPropertyConfig#newBuilder} to create an instance of this class. 36 * 37 * @param <T> refer to Parcel#writeValue(Object) to get a list of all supported types. The class 38 * should be visible to framework as default class loader is being used here. 39 * 40 * @hide 41 */ 42 @SystemApi 43 public class CarPropertyConfig<T> implements Parcelable { 44 private final int mAccess; 45 private final int mAreaType; 46 private final int mChangeMode; 47 private final ArrayList<Integer> mConfigArray; 48 private final String mConfigString; 49 private final float mMaxSampleRate; 50 private final float mMinSampleRate; 51 private final int mPropertyId; 52 private final SparseArray<AreaConfig<T>> mSupportedAreas; 53 private final Class<T> mType; 54 55 private CarPropertyConfig(int access, int areaType, int changeMode, 56 ArrayList<Integer> configArray, String configString, 57 float maxSampleRate, float minSampleRate, int propertyId, 58 SparseArray<AreaConfig<T>> supportedAreas, Class<T> type) { 59 mAccess = access; 60 mAreaType = areaType; 61 mChangeMode = changeMode; 62 mConfigArray = configArray; 63 mConfigString = configString; 64 mMaxSampleRate = maxSampleRate; 65 mMinSampleRate = minSampleRate; 66 mPropertyId = propertyId; 67 mSupportedAreas = supportedAreas; 68 mType = type; 69 } 70 71 public int getAccess() { 72 return mAccess; 73 } 74 public @VehicleAreaType.VehicleAreaTypeValue int getAreaType() { 75 return mAreaType; 76 } 77 public int getChangeMode() { 78 return mChangeMode; 79 } 80 public List<Integer> getConfigArray() { 81 return Collections.unmodifiableList(mConfigArray); 82 } 83 public String getConfigString() { 84 return mConfigString; 85 } 86 public float getMaxSampleRate() { 87 return mMaxSampleRate; 88 } 89 public float getMinSampleRate() { 90 return mMinSampleRate; 91 } 92 public int getPropertyId() { 93 return mPropertyId; 94 } 95 public Class<T> getPropertyType() { 96 return mType; 97 } 98 99 /** Returns true if this property doesn't hold car area-specific configuration */ 100 public boolean isGlobalProperty() { 101 return mAreaType == VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL; 102 } 103 104 public int getAreaCount() { 105 return mSupportedAreas.size(); 106 } 107 108 public int[] getAreaIds() { 109 int[] areaIds = new int[mSupportedAreas.size()]; 110 for (int i = 0; i < areaIds.length; i++) { 111 areaIds[i] = mSupportedAreas.keyAt(i); 112 } 113 return areaIds; 114 } 115 116 /** 117 * Returns the first areaId. 118 * Throws {@link IllegalStateException} if supported area count not equals to one. 119 * */ 120 public int getFirstAndOnlyAreaId() { 121 if (mSupportedAreas.size() != 1) { 122 throw new IllegalStateException("Expected one and only area in this property. Prop: 0x" 123 + Integer.toHexString(mPropertyId)); 124 } 125 return mSupportedAreas.keyAt(0); 126 } 127 128 public boolean hasArea(int areaId) { 129 return mSupportedAreas.indexOfKey(areaId) >= 0; 130 } 131 132 @Nullable 133 public T getMinValue(int areaId) { 134 AreaConfig<T> area = mSupportedAreas.get(areaId); 135 return area == null ? null : area.getMinValue(); 136 } 137 138 @Nullable 139 public T getMaxValue(int areaId) { 140 AreaConfig<T> area = mSupportedAreas.get(areaId); 141 return area == null ? null : area.getMaxValue(); 142 } 143 144 @Nullable 145 public T getMinValue() { 146 AreaConfig<T> area = mSupportedAreas.valueAt(0); 147 return area == null ? null : area.getMinValue(); 148 } 149 150 @Nullable 151 public T getMaxValue() { 152 AreaConfig<T> area = mSupportedAreas.valueAt(0); 153 return area == null ? null : area.getMaxValue(); 154 } 155 156 @Override 157 public int describeContents() { 158 return 0; 159 } 160 161 @Override 162 public void writeToParcel(Parcel dest, int flags) { 163 dest.writeInt(mAccess); 164 dest.writeInt(mAreaType); 165 dest.writeInt(mChangeMode); 166 dest.writeInt(mConfigArray.size()); 167 for (int i = 0; i < mConfigArray.size(); i++) { 168 dest.writeInt(mConfigArray.get(i)); 169 } 170 dest.writeString(mConfigString); 171 dest.writeFloat(mMaxSampleRate); 172 dest.writeFloat(mMinSampleRate); 173 dest.writeInt(mPropertyId); 174 dest.writeInt(mSupportedAreas.size()); 175 for (int i = 0; i < mSupportedAreas.size(); i++) { 176 dest.writeInt(mSupportedAreas.keyAt(i)); 177 dest.writeParcelable(mSupportedAreas.valueAt(i), flags); 178 } 179 dest.writeString(mType.getName()); 180 } 181 182 @SuppressWarnings("unchecked") 183 private CarPropertyConfig(Parcel in) { 184 mAccess = in.readInt(); 185 mAreaType = in.readInt(); 186 mChangeMode = in.readInt(); 187 int configArraySize = in.readInt(); 188 mConfigArray = new ArrayList<Integer>(configArraySize); 189 for (int i = 0; i < configArraySize; i++) { 190 mConfigArray.add(in.readInt()); 191 } 192 mConfigString = in.readString(); 193 mMaxSampleRate = in.readFloat(); 194 mMinSampleRate = in.readFloat(); 195 mPropertyId = in.readInt(); 196 int areaSize = in.readInt(); 197 mSupportedAreas = new SparseArray<>(areaSize); 198 for (int i = 0; i < areaSize; i++) { 199 int areaId = in.readInt(); 200 AreaConfig<T> area = in.readParcelable(getClass().getClassLoader()); 201 mSupportedAreas.put(areaId, area); 202 } 203 String className = in.readString(); 204 try { 205 mType = (Class<T>) Class.forName(className); 206 } catch (ClassNotFoundException e) { 207 throw new IllegalArgumentException("Class not found: " + className); 208 } 209 } 210 211 public static final Creator<CarPropertyConfig> CREATOR = new Creator<CarPropertyConfig>() { 212 @Override 213 public CarPropertyConfig createFromParcel(Parcel in) { 214 return new CarPropertyConfig(in); 215 } 216 217 @Override 218 public CarPropertyConfig[] newArray(int size) { 219 return new CarPropertyConfig[size]; 220 } 221 }; 222 223 @Override 224 public String toString() { 225 return "CarPropertyConfig{" 226 + "mPropertyId=" + mPropertyId 227 + ", mAccess=" + mAccess 228 + ", mAreaType=" + mAreaType 229 + ", mChangeMode=" + mChangeMode 230 + ", mConfigArray=" + mConfigArray 231 + ", mConfigString=" + mConfigString 232 + ", mMaxSampleRate=" + mMaxSampleRate 233 + ", mMinSampleRate=" + mMinSampleRate 234 + ", mSupportedAreas=" + mSupportedAreas 235 + ", mType=" + mType 236 + '}'; 237 } 238 239 public static class AreaConfig<T> implements Parcelable { 240 @Nullable private final T mMinValue; 241 @Nullable private final T mMaxValue; 242 243 private AreaConfig(T minValue, T maxValue) { 244 mMinValue = minValue; 245 mMaxValue = maxValue; 246 } 247 248 public static final Parcelable.Creator<AreaConfig<Object>> CREATOR 249 = getCreator(Object.class); 250 251 private static <E> Parcelable.Creator<AreaConfig<E>> getCreator(final Class<E> clazz) { 252 return new Creator<AreaConfig<E>>() { 253 @Override 254 public AreaConfig<E> createFromParcel(Parcel source) { 255 return new AreaConfig<>(source); 256 } 257 258 @Override @SuppressWarnings("unchecked") 259 public AreaConfig<E>[] newArray(int size) { 260 return (AreaConfig<E>[]) Array.newInstance(clazz, size); 261 } 262 }; 263 } 264 265 @SuppressWarnings("unchecked") 266 private AreaConfig(Parcel in) { 267 mMinValue = (T) in.readValue(getClass().getClassLoader()); 268 mMaxValue = (T) in.readValue(getClass().getClassLoader()); 269 } 270 271 @Nullable public T getMinValue() { return mMinValue; } 272 @Nullable public T getMaxValue() { return mMaxValue; } 273 274 @Override 275 public int describeContents() { 276 return 0; 277 } 278 279 @Override 280 public void writeToParcel(Parcel dest, int flags) { 281 dest.writeValue(mMinValue); 282 dest.writeValue(mMaxValue); 283 } 284 285 @Override 286 public String toString() { 287 return "CarAreaConfig{" + 288 "mMinValue=" + mMinValue + 289 ", mMaxValue=" + mMaxValue + 290 '}'; 291 } 292 } 293 294 /** 295 * Prepare an instance of CarPropertyConfig 296 * 297 * @return Builder<T> 298 */ 299 public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType, 300 int areaCapacity) { 301 return new Builder<>(areaCapacity, areaType, propertyId, type); 302 } 303 304 305 /** 306 * Prepare an instance of CarPropertyConfig 307 * 308 * @return Builder<T> 309 */ 310 public static <T> Builder<T> newBuilder(Class<T> type, int propertyId, int areaType) { 311 return new Builder<>(0, areaType, propertyId, type); 312 } 313 314 public static class Builder<T> { 315 private int mAccess; 316 private final int mAreaType; 317 private int mChangeMode; 318 private final ArrayList<Integer> mConfigArray; 319 private String mConfigString; 320 private float mMaxSampleRate; 321 private float mMinSampleRate; 322 private final int mPropertyId; 323 private final SparseArray<AreaConfig<T>> mSupportedAreas; 324 private final Class<T> mType; 325 326 private Builder(int areaCapacity, int areaType, int propertyId, Class<T> type) { 327 mAreaType = areaType; 328 mConfigArray = new ArrayList<>(); 329 mPropertyId = propertyId; 330 if (areaCapacity != 0) { 331 mSupportedAreas = new SparseArray<>(areaCapacity); 332 } else { 333 mSupportedAreas = new SparseArray<>(); 334 } 335 mType = type; 336 } 337 338 /** 339 * Add supported areas parameter to CarPropertyConfig 340 * 341 * @return Builder<T> 342 */ 343 public Builder<T> addAreas(int[] areaIds) { 344 for (int id : areaIds) { 345 mSupportedAreas.put(id, null); 346 } 347 return this; 348 } 349 350 /** 351 * Add area to CarPropertyConfig 352 * 353 * @return Builder<T> 354 */ 355 public Builder<T> addArea(int areaId) { 356 return addAreaConfig(areaId, null, null); 357 } 358 359 /** 360 * Add areaConfig to CarPropertyConfig 361 * 362 * @return Builder<T> 363 */ 364 public Builder<T> addAreaConfig(int areaId, T min, T max) { 365 if (min == null && max == null) { 366 mSupportedAreas.put(areaId, null); 367 } else { 368 mSupportedAreas.put(areaId, new AreaConfig<>(min, max)); 369 } 370 return this; 371 } 372 373 /** 374 * Set access parameter to CarPropertyConfig 375 * 376 * @return Builder<T> 377 */ 378 public Builder<T> setAccess(int access) { 379 mAccess = access; 380 return this; 381 } 382 383 /** 384 * Set changeMode parameter to CarPropertyConfig 385 * 386 * @return Builder<T> 387 */ 388 public Builder<T> setChangeMode(int changeMode) { 389 mChangeMode = changeMode; 390 return this; 391 } 392 393 /** 394 * Set configArray parameter to CarPropertyConfig 395 * 396 * @return Builder<T> 397 */ 398 public Builder<T> setConfigArray(ArrayList<Integer> configArray) { 399 mConfigArray.clear(); 400 mConfigArray.addAll(configArray); 401 return this; 402 } 403 404 /** 405 * Set configString parameter to CarPropertyConfig 406 * 407 * @return Builder<T> 408 */ 409 public Builder<T> setConfigString(String configString) { 410 mConfigString = configString; 411 return this; 412 } 413 414 /** 415 * Set maxSampleRate parameter to CarPropertyConfig 416 * 417 * @return Builder<T> 418 */ 419 public Builder<T> setMaxSampleRate(float maxSampleRate) { 420 mMaxSampleRate = maxSampleRate; 421 return this; 422 } 423 424 /** 425 * Set minSampleRate parameter to CarPropertyConfig 426 * 427 * @return Builder<T> 428 */ 429 public Builder<T> setMinSampleRate(float minSampleRate) { 430 mMinSampleRate = minSampleRate; 431 return this; 432 } 433 434 public CarPropertyConfig<T> build() { 435 return new CarPropertyConfig<>(mAccess, mAreaType, mChangeMode, mConfigArray, 436 mConfigString, mMaxSampleRate, mMinSampleRate, 437 mPropertyId, mSupportedAreas, mType); 438 } 439 } 440 } 441