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