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.SystemApi; 22 import android.os.Parcel; 23 import android.os.Parcelable; 24 25 import java.nio.charset.Charset; 26 27 /** 28 * Stores values broken down by area for a vehicle property. 29 * 30 * @param <T> refer to Parcel#writeValue(Object) to get a list of all supported types. The class 31 * should be visible to framework as default class loader is being used here. 32 * 33 * @hide 34 */ 35 @SystemApi 36 public class CarPropertyValue<T> implements Parcelable { 37 38 private final static Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); 39 40 private final int mPropertyId; 41 private final int mAreaId; 42 private final T mValue; 43 CarPropertyValue(int propertyId, T value)44 public CarPropertyValue(int propertyId, T value) { 45 this(propertyId, 0, value); 46 } 47 CarPropertyValue(int propertyId, int areaId, T value)48 public CarPropertyValue(int propertyId, int areaId, T value) { 49 mPropertyId = propertyId; 50 mAreaId = areaId; 51 mValue = value; 52 } 53 54 @SuppressWarnings("unchecked") CarPropertyValue(Parcel in)55 public CarPropertyValue(Parcel in) { 56 mPropertyId = in.readInt(); 57 mAreaId = in.readInt(); 58 String valueClassName = in.readString(); 59 Class<?> valueClass; 60 try { 61 valueClass = Class.forName(valueClassName); 62 } catch (ClassNotFoundException e) { 63 throw new IllegalArgumentException("Class not found: " + valueClassName); 64 } 65 66 if (String.class.equals(valueClass)) { 67 byte[] bytes = in.readBlob(); 68 mValue = (T) new String(bytes, DEFAULT_CHARSET); 69 } else if (byte[].class.equals(valueClass)) { 70 mValue = (T) in.readBlob(); 71 } else { 72 mValue = (T) in.readValue(valueClass.getClassLoader()); 73 } 74 } 75 76 public static final Creator<CarPropertyValue> CREATOR = new Creator<CarPropertyValue>() { 77 @Override 78 public CarPropertyValue createFromParcel(Parcel in) { 79 return new CarPropertyValue(in); 80 } 81 82 @Override 83 public CarPropertyValue[] newArray(int size) { 84 return new CarPropertyValue[size]; 85 } 86 }; 87 88 @Override describeContents()89 public int describeContents() { 90 return 0; 91 } 92 93 @Override writeToParcel(Parcel dest, int flags)94 public void writeToParcel(Parcel dest, int flags) { 95 dest.writeInt(mPropertyId); 96 dest.writeInt(mAreaId); 97 98 Class<?> valueClass = mValue == null ? null : mValue.getClass(); 99 dest.writeString(valueClass == null ? null : valueClass.getName()); 100 101 // Special handling for String and byte[] to mitigate transaction buffer limitations. 102 if (String.class.equals(valueClass)) { 103 dest.writeBlob(((String)mValue).getBytes(DEFAULT_CHARSET)); 104 } else if (byte[].class.equals(valueClass)) { 105 dest.writeBlob((byte[]) mValue); 106 } else { 107 dest.writeValue(mValue); 108 } 109 } 110 getPropertyId()111 public int getPropertyId() { 112 return mPropertyId; 113 } 114 getAreaId()115 public int getAreaId() { 116 return mAreaId; 117 } 118 getValue()119 public T getValue() { 120 return mValue; 121 } 122 123 @Override toString()124 public String toString() { 125 return "CarPropertyValue{" + 126 "mPropertyId=0x" + toHexString(mPropertyId) + 127 ", mAreaId=0x" + toHexString(mAreaId) + 128 ", mValue=" + mValue + 129 '}'; 130 } 131 } 132