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 static java.lang.Integer.toHexString; 20 21 import android.annotation.IntDef; 22 import android.annotation.SystemApi; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 26 import java.lang.annotation.Retention; 27 import java.lang.annotation.RetentionPolicy; 28 import java.nio.charset.Charset; 29 30 /** 31 * Stores values broken down by area for a vehicle property. 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 CarPropertyValue<T> implements Parcelable { 40 private final static Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 41 42 private final int mPropertyId; 43 private final int mAreaId; 44 private final int mStatus; 45 private final long mTimestamp; 46 private final T mValue; 47 48 /** @hide */ 49 @IntDef({ 50 STATUS_AVAILABLE, 51 STATUS_UNAVAILABLE, 52 STATUS_ERROR 53 }) 54 @Retention(RetentionPolicy.SOURCE) 55 public @interface PropertyStatus {} 56 57 /** @hide */ 58 public static final int STATUS_AVAILABLE = 0; 59 60 /** @hide */ 61 public static final int STATUS_UNAVAILABLE = 1; 62 63 /** @hide */ 64 public static final int STATUS_ERROR = 2; 65 CarPropertyValue(int propertyId, int areaId, T value)66 public CarPropertyValue(int propertyId, int areaId, T value) { 67 this(propertyId, areaId, 0, 0, value); 68 } 69 CarPropertyValue(int propertyId, int areaId, int status, long timestamp, T value)70 public CarPropertyValue(int propertyId, int areaId, int status, long timestamp, T value) { 71 mPropertyId = propertyId; 72 mAreaId = areaId; 73 mStatus = status; 74 mTimestamp = timestamp; 75 mValue = value; 76 } 77 78 @SuppressWarnings("unchecked") CarPropertyValue(Parcel in)79 public CarPropertyValue(Parcel in) { 80 mPropertyId = in.readInt(); 81 mAreaId = in.readInt(); 82 mStatus = in.readInt(); 83 mTimestamp = in.readLong(); 84 String valueClassName = in.readString(); 85 Class<?> valueClass; 86 try { 87 valueClass = Class.forName(valueClassName); 88 } catch (ClassNotFoundException e) { 89 throw new IllegalArgumentException("Class not found: " + valueClassName); 90 } 91 92 if (String.class.equals(valueClass)) { 93 byte[] bytes = in.readBlob(); 94 mValue = (T) new String(bytes, DEFAULT_CHARSET); 95 } else if (byte[].class.equals(valueClass)) { 96 mValue = (T) in.readBlob(); 97 } else { 98 mValue = (T) in.readValue(valueClass.getClassLoader()); 99 } 100 } 101 102 public static final Creator<CarPropertyValue> CREATOR = new Creator<CarPropertyValue>() { 103 @Override 104 public CarPropertyValue createFromParcel(Parcel in) { 105 return new CarPropertyValue(in); 106 } 107 108 @Override 109 public CarPropertyValue[] newArray(int size) { 110 return new CarPropertyValue[size]; 111 } 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.writeInt(mAreaId); 123 dest.writeInt(mStatus); 124 dest.writeLong(mTimestamp); 125 126 Class<?> valueClass = mValue == null ? null : mValue.getClass(); 127 dest.writeString(valueClass == null ? null : valueClass.getName()); 128 129 // Special handling for String and byte[] to mitigate transaction buffer limitations. 130 if (String.class.equals(valueClass)) { 131 dest.writeBlob(((String)mValue).getBytes(DEFAULT_CHARSET)); 132 } else if (byte[].class.equals(valueClass)) { 133 dest.writeBlob((byte[]) mValue); 134 } else { 135 dest.writeValue(mValue); 136 } 137 } 138 getPropertyId()139 public int getPropertyId() { 140 return mPropertyId; 141 } 142 getAreaId()143 public int getAreaId() { 144 return mAreaId; 145 } 146 getStatus()147 public @PropertyStatus int getStatus() { 148 return mStatus; 149 } 150 getTimestamp()151 public long getTimestamp() { 152 return mTimestamp; 153 } 154 getValue()155 public T getValue() { 156 return mValue; 157 } 158 159 @Override toString()160 public String toString() { 161 return "CarPropertyValue{" + 162 "mPropertyId=0x" + toHexString(mPropertyId) + 163 ", mAreaId=0x" + toHexString(mAreaId) + 164 ", mStatus=" + mStatus + 165 ", mTimestamp=" + mTimestamp + 166 ", mValue=" + mValue + 167 '}'; 168 } 169 } 170