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.os.Parcel; 22 import android.os.Parcelable; 23 import android.util.SparseArray; 24 25 import java.lang.reflect.Array; 26 27 /** 28 * Represents general information about car property such as data type and min/max ranges for car 29 * areas (if applicable). This class supposed to be immutable, parcelable and could be passed over. 30 * 31 * <p>Use {@link CarPropertyConfig#newBuilder} to create an instance of this class. 32 * 33 * @param <T> refer to Parcel#writeValue(Object) to get a list of all supported types. The class 34 * should be visible to framework as default class loader is being used here. 35 * 36 * @hide 37 */ 38 @SystemApi 39 public class CarPropertyConfig<T> implements Parcelable { 40 private final int mPropertyId; 41 private final Class<T> mType; 42 private final int mAreaType; 43 private final SparseArray<AreaConfig<T>> mSupportedAreas; 44 CarPropertyConfig(Class<T> type, int propertyId, int areaType, SparseArray<AreaConfig<T>> supportedAreas)45 private CarPropertyConfig(Class<T> type, int propertyId, int areaType, 46 SparseArray<AreaConfig<T>> supportedAreas) { 47 mPropertyId = propertyId; 48 mType = type; 49 mAreaType = areaType; 50 mSupportedAreas = supportedAreas; 51 } 52 getPropertyId()53 public int getPropertyId() { return mPropertyId; } getPropertyType()54 public Class<T> getPropertyType() { return mType; } getAreaType()55 public int getAreaType() { return mAreaType; } 56 57 /** Returns true if this property doesn't hold car area-specific configuration */ isGlobalProperty()58 public boolean isGlobalProperty() { 59 return mAreaType == 0; 60 } 61 getAreaCount()62 public int getAreaCount() { 63 return mSupportedAreas.size(); 64 } 65 getAreaIds()66 public int[] getAreaIds() { 67 int[] areaIds = new int[mSupportedAreas.size()]; 68 for (int i = 0; i < areaIds.length; i++) { 69 areaIds[i] = mSupportedAreas.keyAt(i); 70 } 71 return areaIds; 72 } 73 74 /** 75 * Returns the first areaId. 76 * Throws {@link IllegalStateException} if supported area count not equals to one. 77 * */ getFirstAndOnlyAreaId()78 public int getFirstAndOnlyAreaId() { 79 if (mSupportedAreas.size() != 1) { 80 throw new IllegalStateException("Expected one and only area in this property. Prop: 0x" 81 + Integer.toHexString(mPropertyId)); 82 } 83 return mSupportedAreas.keyAt(0); 84 } 85 hasArea(int areaId)86 public boolean hasArea(int areaId) { 87 return mSupportedAreas.indexOfKey(areaId) != -1; 88 } 89 90 @Nullable getMinValue(int areaId)91 public T getMinValue(int areaId) { 92 AreaConfig<T> area = mSupportedAreas.get(areaId); 93 return area == null ? null : area.getMinValue(); 94 } 95 96 @Nullable getMaxValue(int areaId)97 public T getMaxValue(int areaId) { 98 AreaConfig<T> area = mSupportedAreas.get(areaId); 99 return area == null ? null : area.getMaxValue(); 100 } 101 102 @Nullable getMinValue()103 public T getMinValue() { 104 AreaConfig<T> area = mSupportedAreas.valueAt(0); 105 return area == null ? null : area.getMinValue(); 106 } 107 108 @Nullable getMaxValue()109 public T getMaxValue() { 110 AreaConfig<T> area = mSupportedAreas.valueAt(0); 111 return area == null ? null : area.getMaxValue(); 112 } 113 114 @Override describeContents()115 public int describeContents() { 116 return 0; 117 } 118 119 @Override writeToParcel(Parcel dest, int flags)120 public void writeToParcel(Parcel dest, int flags) { 121 dest.writeInt(mPropertyId); 122 dest.writeSerializable(mType); 123 dest.writeInt(mAreaType); 124 dest.writeInt(mSupportedAreas.size()); 125 for (int i = 0; i < mSupportedAreas.size(); i++) { 126 dest.writeInt(mSupportedAreas.keyAt(i)); 127 dest.writeParcelable(mSupportedAreas.valueAt(i), flags); 128 } 129 } 130 131 @SuppressWarnings("unchecked") CarPropertyConfig(Parcel in)132 private CarPropertyConfig(Parcel in) { 133 mPropertyId = in.readInt(); 134 mType = (Class<T>) in.readSerializable(); 135 mAreaType = in.readInt(); 136 int areaSize = in.readInt(); 137 mSupportedAreas = new SparseArray<>(areaSize); 138 for (int i = 0; i < areaSize; i++) { 139 int areaId = in.readInt(); 140 AreaConfig<T> area = in.readParcelable(getClass().getClassLoader()); 141 mSupportedAreas.put(areaId, area); 142 } 143 } 144 145 public static final Creator<CarPropertyConfig> CREATOR = new Creator<CarPropertyConfig>() { 146 @Override 147 public CarPropertyConfig createFromParcel(Parcel in) { 148 return new CarPropertyConfig(in); 149 } 150 151 @Override 152 public CarPropertyConfig[] newArray(int size) { 153 return new CarPropertyConfig[size]; 154 } 155 }; 156 157 @Override toString()158 public String toString() { 159 return "CarPropertyConfig{" + 160 "mPropertyId=" + mPropertyId + 161 ", mType=" + mType + 162 ", mAreaType=" + mAreaType + 163 ", mSupportedAreas=" + mSupportedAreas + 164 '}'; 165 } 166 167 public static class AreaConfig<T> implements Parcelable { 168 @Nullable private final T mMinValue; 169 @Nullable private final T mMaxValue; 170 AreaConfig(T minValue, T maxValue)171 private AreaConfig(T minValue, T maxValue) { 172 mMinValue = minValue; 173 mMaxValue = maxValue; 174 } 175 176 public static final Parcelable.Creator<AreaConfig<Object>> CREATOR 177 = getCreator(Object.class); 178 getCreator(final Class<E> clazz)179 private static <E> Parcelable.Creator<AreaConfig<E>> getCreator(final Class<E> clazz) { 180 return new Creator<AreaConfig<E>>() { 181 @Override 182 public AreaConfig<E> createFromParcel(Parcel source) { 183 return new AreaConfig<>(source); 184 } 185 186 @Override @SuppressWarnings("unchecked") 187 public AreaConfig<E>[] newArray(int size) { 188 return (AreaConfig<E>[]) Array.newInstance(clazz, size); 189 } 190 }; 191 } 192 193 @SuppressWarnings("unchecked") AreaConfig(Parcel in)194 private AreaConfig(Parcel in) { 195 mMinValue = (T) in.readValue(getClass().getClassLoader()); 196 mMaxValue = (T) in.readValue(getClass().getClassLoader()); 197 } 198 getMinValue()199 @Nullable public T getMinValue() { return mMinValue; } getMaxValue()200 @Nullable public T getMaxValue() { return mMaxValue; } 201 202 @Override describeContents()203 public int describeContents() { 204 return 0; 205 } 206 207 @Override writeToParcel(Parcel dest, int flags)208 public void writeToParcel(Parcel dest, int flags) { 209 dest.writeValue(mMinValue); 210 dest.writeValue(mMaxValue); 211 } 212 213 @Override toString()214 public String toString() { 215 return "CarAreaConfig{" + 216 "mMinValue=" + mMinValue + 217 ", mMaxValue=" + mMaxValue + 218 '}'; 219 } 220 } 221 222 public static <T> Builder<T> newBuilder(Class<T> clazz, int propertyId, int areaType, 223 int areaCapacity) { 224 return new Builder<>(clazz, propertyId, areaType, areaCapacity); 225 } 226 227 228 public static <T> Builder<T> newBuilder(Class<T> clazz, int propertyId, int areaType) { 229 return newBuilder(clazz, propertyId, areaType, 0); 230 } 231 232 public static class Builder<T> { 233 private final Class<T> mType; 234 private final int mPropertyId; 235 private final int mAreaType; 236 private final SparseArray<AreaConfig<T>> mAreas; 237 238 private Builder(Class<T> type, int propertyId, int areaType, int areaCapacity) { 239 mType = type; 240 mPropertyId = propertyId; 241 mAreaType = areaType; 242 if (areaCapacity != 0) { 243 mAreas = new SparseArray<>(areaCapacity); 244 } else { 245 mAreas = new SparseArray<>(); 246 } 247 } 248 249 public Builder<T> addAreas(int[] areaIds) { 250 for (int id : areaIds) { 251 mAreas.put(id, null); 252 } 253 return this; 254 } 255 256 public Builder<T> addArea(int areaId) { 257 return addAreaConfig(areaId, null, null); 258 } 259 260 public Builder<T> addAreaConfig(int areaId, T min, T max) { 261 if (min == null && max == null) { 262 mAreas.put(areaId, null); 263 } else { 264 mAreas.put(areaId, new AreaConfig<>(min, max)); 265 } 266 return this; 267 } 268 269 public CarPropertyConfig<T> build() { 270 return new CarPropertyConfig<>(mType, mPropertyId, mAreaType, mAreas); 271 } 272 } 273 } 274