/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.car.hardware;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.SparseArray;
import java.lang.reflect.Array;
/**
* Represents general information about car property such as data type and min/max ranges for car
* areas (if applicable). This class supposed to be immutable, parcelable and could be passed over.
*
*
Use {@link CarPropertyConfig#newBuilder} to create an instance of this class.
*
* @param refer to Parcel#writeValue(Object) to get a list of all supported types. The class
* should be visible to framework as default class loader is being used here.
*
* @hide
*/
@SystemApi
public class CarPropertyConfig implements Parcelable {
private final int mPropertyId;
private final Class mType;
private final int mAreaType;
private final SparseArray> mSupportedAreas;
private CarPropertyConfig(Class type, int propertyId, int areaType,
SparseArray> supportedAreas) {
mPropertyId = propertyId;
mType = type;
mAreaType = areaType;
mSupportedAreas = supportedAreas;
}
public int getPropertyId() { return mPropertyId; }
public Class getPropertyType() { return mType; }
public int getAreaType() { return mAreaType; }
/** Returns true if this property doesn't hold car area-specific configuration */
public boolean isGlobalProperty() {
return mAreaType == 0;
}
public int getAreaCount() {
return mSupportedAreas.size();
}
public int[] getAreaIds() {
int[] areaIds = new int[mSupportedAreas.size()];
for (int i = 0; i < areaIds.length; i++) {
areaIds[i] = mSupportedAreas.keyAt(i);
}
return areaIds;
}
/**
* Returns the first areaId.
* Throws {@link IllegalStateException} if supported area count not equals to one.
* */
public int getFirstAndOnlyAreaId() {
if (mSupportedAreas.size() != 1) {
throw new IllegalStateException("Expected one and only area in this property. Prop: 0x"
+ Integer.toHexString(mPropertyId));
}
return mSupportedAreas.keyAt(0);
}
public boolean hasArea(int areaId) {
return mSupportedAreas.indexOfKey(areaId) != -1;
}
@Nullable
public T getMinValue(int areaId) {
AreaConfig area = mSupportedAreas.get(areaId);
return area == null ? null : area.getMinValue();
}
@Nullable
public T getMaxValue(int areaId) {
AreaConfig area = mSupportedAreas.get(areaId);
return area == null ? null : area.getMaxValue();
}
@Nullable
public T getMinValue() {
AreaConfig area = mSupportedAreas.valueAt(0);
return area == null ? null : area.getMinValue();
}
@Nullable
public T getMaxValue() {
AreaConfig area = mSupportedAreas.valueAt(0);
return area == null ? null : area.getMaxValue();
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mPropertyId);
dest.writeSerializable(mType);
dest.writeInt(mAreaType);
dest.writeInt(mSupportedAreas.size());
for (int i = 0; i < mSupportedAreas.size(); i++) {
dest.writeInt(mSupportedAreas.keyAt(i));
dest.writeParcelable(mSupportedAreas.valueAt(i), flags);
}
}
@SuppressWarnings("unchecked")
private CarPropertyConfig(Parcel in) {
mPropertyId = in.readInt();
mType = (Class) in.readSerializable();
mAreaType = in.readInt();
int areaSize = in.readInt();
mSupportedAreas = new SparseArray<>(areaSize);
for (int i = 0; i < areaSize; i++) {
int areaId = in.readInt();
AreaConfig area = in.readParcelable(getClass().getClassLoader());
mSupportedAreas.put(areaId, area);
}
}
public static final Creator CREATOR = new Creator() {
@Override
public CarPropertyConfig createFromParcel(Parcel in) {
return new CarPropertyConfig(in);
}
@Override
public CarPropertyConfig[] newArray(int size) {
return new CarPropertyConfig[size];
}
};
@Override
public String toString() {
return "CarPropertyConfig{" +
"mPropertyId=" + mPropertyId +
", mType=" + mType +
", mAreaType=" + mAreaType +
", mSupportedAreas=" + mSupportedAreas +
'}';
}
public static class AreaConfig implements Parcelable {
@Nullable private final T mMinValue;
@Nullable private final T mMaxValue;
private AreaConfig(T minValue, T maxValue) {
mMinValue = minValue;
mMaxValue = maxValue;
}
public static final Parcelable.Creator> CREATOR
= getCreator(Object.class);
private static Parcelable.Creator> getCreator(final Class clazz) {
return new Creator>() {
@Override
public AreaConfig createFromParcel(Parcel source) {
return new AreaConfig<>(source);
}
@Override @SuppressWarnings("unchecked")
public AreaConfig[] newArray(int size) {
return (AreaConfig[]) Array.newInstance(clazz, size);
}
};
}
@SuppressWarnings("unchecked")
private AreaConfig(Parcel in) {
mMinValue = (T) in.readValue(getClass().getClassLoader());
mMaxValue = (T) in.readValue(getClass().getClassLoader());
}
@Nullable public T getMinValue() { return mMinValue; }
@Nullable public T getMaxValue() { return mMaxValue; }
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeValue(mMinValue);
dest.writeValue(mMaxValue);
}
@Override
public String toString() {
return "CarAreaConfig{" +
"mMinValue=" + mMinValue +
", mMaxValue=" + mMaxValue +
'}';
}
}
public static Builder newBuilder(Class clazz, int propertyId, int areaType,
int areaCapacity) {
return new Builder<>(clazz, propertyId, areaType, areaCapacity);
}
public static Builder newBuilder(Class clazz, int propertyId, int areaType) {
return newBuilder(clazz, propertyId, areaType, 0);
}
public static class Builder {
private final Class mType;
private final int mPropertyId;
private final int mAreaType;
private final SparseArray> mAreas;
private Builder(Class type, int propertyId, int areaType, int areaCapacity) {
mType = type;
mPropertyId = propertyId;
mAreaType = areaType;
if (areaCapacity != 0) {
mAreas = new SparseArray<>(areaCapacity);
} else {
mAreas = new SparseArray<>();
}
}
public Builder addAreas(int[] areaIds) {
for (int id : areaIds) {
mAreas.put(id, null);
}
return this;
}
public Builder addArea(int areaId) {
return addAreaConfig(areaId, null, null);
}
public Builder addAreaConfig(int areaId, T min, T max) {
if (min == null && max == null) {
mAreas.put(areaId, null);
} else {
mAreas.put(areaId, new AreaConfig<>(min, max));
}
return this;
}
public CarPropertyConfig build() {
return new CarPropertyConfig<>(mType, mPropertyId, mAreaType, mAreas);
}
}
}